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=(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 ",DC.Maxflow(src,dst)==n?"YES":"NO"); 137 } 138 return 0; 139 }