首页 > 代码库 > 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(状态压缩+最大流)