首页 > 代码库 > HDU 3605 Escape(状态压缩+最大流)
HDU 3605 Escape(状态压缩+最大流)
http://acm.hdu.edu.cn/showproblem.php?pid=3605
题意:
有n个人和m个星球,每个人可以去某些星球和不可以去某些星球,并且每个星球有最大居住人数,判断是否所有人都能去这m个星球之中。
思路:
这道题建图是关键,因为n的数量很大,如果直接将源点和人相连,是会超时的,因为m≤10,所以每个人的选择可以用二进制来存储,这样最多也就1<<m-1种状态,相同的就可以放在一起处理了。
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstring> 5 #include<queue> 6 using namespace std; 7 8 const int maxn=1500; 9 const int INF=0x3f3f3f3f; 10 11 struct Edge 12 { 13 int from,to,cap,flow; 14 Edge(int u,int v,int w,int f):from(u),to(v),cap(w),flow(f){} 15 }; 16 17 struct Dinic 18 { 19 int n,m,s,t; 20 vector<Edge> edges; 21 vector<int> G[maxn]; 22 bool vis[maxn]; 23 int cur[maxn]; 24 int d[maxn]; 25 26 void init(int n) 27 { 28 this->n=n; 29 for(int i=0;i<n;++i) G[i].clear(); 30 edges.clear(); 31 } 32 33 void AddEdge(int from,int to,int cap) 34 { 35 edges.push_back( Edge(from,to,cap,0) ); 36 edges.push_back( Edge(to,from,0,0) ); 37 m=edges.size(); 38 G[from].push_back(m-2); 39 G[to].push_back(m-1); 40 } 41 42 bool BFS() 43 { 44 queue<int> Q; 45 memset(vis,0,sizeof(vis)); 46 vis[s]=true; 47 d[s]=0; 48 Q.push(s); 49 while(!Q.empty()) 50 { 51 int x=Q.front(); Q.pop(); 52 for(int i=0;i<G[x].size();++i) 53 { 54 Edge& e=edges[G[x][i]]; 55 if(!vis[e.to] && e.cap>e.flow) 56 { 57 vis[e.to]=true; 58 d[e.to]=d[x]+1; 59 Q.push(e.to); 60 } 61 } 62 } 63 return vis[t]; 64 } 65 66 int DFS(int x,int a) 67 { 68 if(x==t || a==0) return a; 69 int flow=0, f; 70 for(int &i=cur[x];i<G[x].size();++i) 71 { 72 Edge &e=edges[G[x][i]]; 73 if(d[e.to]==d[x]+1 && (f=DFS(e.to,min(a,e.cap-e.flow) ) )>0) 74 { 75 e.flow +=f; 76 edges[G[x][i]^1].flow -=f; 77 flow +=f; 78 a -=f; 79 if(a==0) break; 80 } 81 } 82 return flow; 83 } 84 85 int Maxflow(int s,int t) 86 { 87 this->s=s; this->t=t; 88 int flow=0; 89 while(BFS()) 90 { 91 memset(cur,0,sizeof(cur)); 92 flow +=DFS(s,INF); 93 } 94 return flow; 95 } 96 }DC; 97 98 int n,m; 99 int num[maxn];100 int src,dst;101 102 int main()103 {104 while(~scanf("%d%d",&n,&m))105 {106 memset(num,0,sizeof(num));107 for(int i=1;i<=n;i++)108 {109 int count=0;110 for(int j=m-1;j>=0;--j)111 {112 int p;113 scanf("%d",&p);114 if(p) count |= 1<<j;115 }116 ++num[count];117 }118 119 src=http://www.mamicode.com/(1<<m)+m;120 dst=(1<<m)+1+m;121 DC.init((1<<m)+2+m);122 for(int i=0;i<(1<<m);++i)123 if(num[i])124 {125 DC.AddEdge(src,i,num[i]);126 for(int j=0;j<m;++j)if(i&(1<<j))127 DC.AddEdge(i,(1<<m)+j,INF);128 }129 for(int i=0;i<m;++i)130 {131 int p;132 scanf("%d",&p);133 DC.AddEdge((1<<m)+i,dst,p);134 }135 136 printf("%s\n",DC.Maxflow(src,dst)==n?"YES":"NO");137 }138 return 0;139 }
HDU 3605 Escape(状态压缩+最大流)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。