HDU 3605 Escape(状态压缩+最大流)

Posted 谦谦君子,陌上其华

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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=(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(状态压缩+最大流)的主要内容,如果未能解决你的问题,请参考以下文章

HDU 3605 最大流+状态压缩

HDU 3605 Escape (最大流)

HDU 3605 Escape(状压+最大流)

HDU3605(KB11-M 状态压缩+最大流)

HDU3605: Escape-二进制优化建图-最大流

hdu3605最大流