标签:input ane whether bottom void mit struct put uri
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 9430 Accepted Submission(s): 2234
题目链接:HDU 3605
比较入门的一道最大流,显然可以想到是超级源点S->人连一条为流量1的边;人->可达的星球连一条流量为1的边;星球->超级汇点T连一条容量为给定的星球容量的边。但是这样就超时了。
膜了一下正确的做法,因为星球数不超过10,显然一个人的选择状态最多$2^{10}=1024$种,然后就把状态代替了人,因此上面的建图中把人改为二进制的状压转化为10进制的数值i即可。
代码:
#include <stdio.h> #include <bits/stdc++.h> using namespace std; #define INF 0x3f3f3f3f #define CLR(arr,val) memset(arr,val,sizeof(arr)) #define LC(x) (x<<1) #define RC(x) ((x<<1)+1) #define MID(x,y) ((x+y)>>1) typedef pair<int,int> pii; typedef long long LL; const double PI=acos(-1.0); const int S=1050; struct edge { int to,nxt; int cap; }; edge E[S*23]; int head[S],tot; bitset<S> vis; int st[S]; void init() { CLR(head,-1); tot=0; CLR(st,0); } inline void add(int s,int t,int c) { E[tot].to=t; E[tot].cap=c; E[tot].nxt=head[s]; head[s]=tot++; E[tot].cap=0; E[tot].to=s; E[tot].nxt=head[t]; head[t]=tot++; } int dfs(int s,int t,int f) { if(s==t) return f; vis[s]=1; for (int i=head[s]; ~i; i=E[i].nxt) { int v=E[i].to; if(!vis[v]&&E[i].cap>0) { int d=dfs(v,t,min(f,E[i].cap)); if(d>0) { E[i].cap-=d; E[i^1].cap+=d; return d; } } } return 0; } int max_flow(int s,int t) { int ret=0; int f; while (true) { vis.reset(); f=dfs(s,t,INF); if(!f) break; ret+=f; } return ret; } int main(void) { int n,m,i,j,c,s; while (~scanf("%d%d",&n,&m)) { init(); int S=0; int T=(1<<m)+m; for (i=1; i<=n; ++i) { int S=0; for (j=0; j<m; ++j) { scanf("%d",&s); if(s) S|=(1<<j); } ++st[S]; } int R=1<<m; for (i=1; i<R; ++i) { if(st[i]) { add(S,i,st[i]); for (j=0; j<m; ++j) { if(i&(1<<j)) add(i,R+j,st[i]); } } } for (i=0; i<m; ++i) { scanf("%d",&c); add(R+i,T,c); } puts(max_flow(S,T)==n?"YES":"NO"); } return 0; }
标签:input ane whether bottom void mit struct put uri
原文地址:http://www.cnblogs.com/Blackops/p/6147845.html