BZOJ3836 : [Poi2014]Tourism
2015-10-05 02:52
351 查看
对于一个连通块,取一个点进行dfs,得到一棵dfs搜索树,则这棵树的深度不超过10,且所有额外边都是前向边。
对于每个点x,设S为三进制状态,S第i位表示根到x路径上深度为i的点的状态:
0:选了
1:没选,且没满足
2:没选,且已满足
设f[i][j]表示考虑根到x路径上深度为i的点时这些点的状态为j时的最小费用,然后按DFS序进行DP即可。
时间复杂度$O((n+m)3^{10})$,空间复杂度$O(10\times3^{10})$。
对于每个点x,设S为三进制状态,S第i位表示根到x路径上深度为i的点的状态:
0:选了
1:没选,且没满足
2:没选,且已满足
设f[i][j]表示考虑根到x路径上深度为i的点时这些点的状态为j时的最小费用,然后按DFS序进行DP即可。
时间复杂度$O((n+m)3^{10})$,空间复杂度$O(10\times3^{10})$。
#include<cstdio> const int N=20010,M=50010,K=11,inf=2000000000; int n,m,i,x,y,a ,g ,v[M],nxt[M],ed,vis ,d ,q[K],pow[K],f[K][59050],ans; inline void add(int x,int y){v[++ed]=y;nxt[ed]=g[x];g[x]=ed;} inline int bit(int x,int y){return x/pow[y]%3;} inline void up(int&x,int y){if(x>y)x=y;} inline int min(int x,int y){return x<y?x:y;} void dfs(int x,int y){ vis[x]=1,d[x]=y; if(!y)f[0][0]=a[x],f[0][1]=0,f[0][2]=inf; else{ int cnt=0; for(int i=g[x];i;i=nxt[i]){ int u=v[i]; if(vis[u]&&d[u]<y)q[cnt++]=d[u]; } for(int S=pow[y+1]-1;~S;S--)f[y][S]=inf; for(int S=pow[y]-1;~S;S--){ int U=1,V=S; for(int i=0;i<cnt;i++)if(bit(S,q[i])==0)U=2;else if(bit(S,q[i])==1)V+=pow[q[i]]; up(f[y][S+U*pow[y]],f[y-1][S]); up(f[y][V],f[y-1][S]+a[x]); } } for(int i=g[x];i;i=nxt[i]){ int u=v[i]; if(!vis[u]){ dfs(u,y+1); for(int S=0;S<pow[y+1];S++)f[y][S]=min(f[y+1][S],f[y+1][S+2*pow[y+1]]); } } } int main(){ for(pow[0]=i=1;i<K;i++)pow[i]=pow[i-1]*3; scanf("%d%d",&n,&m); for(i=1;i<=n;i++)scanf("%d",&a[i]); while(m--)scanf("%d%d",&x,&y),add(x,y),add(y,x); for(i=1;i<=n;i++)if(!vis[i])dfs(i,0),ans+=min(f[0][0],f[0][2]); return printf("%d",ans),0; }
相关文章推荐
- Eclipse各种优化,美化——主题(护眼色)
- Eclipse各种优化,美化——提示
- LXC(Linux Container)
- git oschina无密钥提交
- GitHub for Windows与IntelliJ整合
- HDU 1072 Nightmare 基础BFS
- Linux slab basic introduce
- 什么是IaaS, PaaS和SaaS及其区别
- Linux学习笔记<Sed最全整理>
- Linux学习笔记<Sed最全整理>
- linux系统设置IP方法记录
- 【转】C#文件操作大全
- 【转】const和static readonly
- HDU-3320
- 使用VirtualBox + Vagrant打造属于自己的开发环境2
- python中的range()函数详解
- 2015/10/4 iOS 笔记 细节 简单-代理过程 UITableView
- [一个经典的多线程同步问题]解决方案三:互斥量Mutex
- JS 函数总结
- LINGO中的集