HDU 3605Escape

来源:互联网 发布:如何进行软件开发 编辑:程序博客网 时间:2024/06/05 22:44
题意:有n个人要移居m个星球,给出每个合适的星球,每个星球最多能容纳的人数,问是否所有人都可以移居。(1N105,1M10)

 很明显这里的边有超过1e6条,所以我能直接跑,然后你会发现什么星球竟然只有10个,那么根据鸽巢原理我能不能想到,会有很多很多的人的选择是重复的,不重复的选择最多有2^10种,所以我们选择用二进制判重加缩点的方式来减少边的数量,然后就是跑最大流就可以了。

#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <algorithm>#include <cmath>#include <queue>using namespace std;typedef long long LL;const int INF = 0x3f3f3f3f;const int maxn = 100000+100;inline int read(){    int x=0,f=1;char ch=getchar();    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}    return x*f;}int n,m;struct Info{int from,to,c,flow,next;}edge[maxn<<1];int head[maxn],level[maxn],cnt;void ADD(int u,int v,int w){edge[cnt].from = u;edge[cnt].to = v;edge[cnt].c = edge[cnt].flow = w;edge[cnt].next = head[u];head[u] = cnt++;edge[cnt].from = v;edge[cnt].to = u;edge[cnt].c = edge[cnt].flow = 0;edge[cnt].next = head[v];head[v] = cnt++;}bool bfs(int S,int E){memset(level,-1,sizeof(level));level[S] = 0;queue<int>Q;Q.push(S);while(!Q.empty()){int u = Q.front();Q.pop();for(int i = head[u]; ~i; i = edge[i].next){int v = edge[i].to;if(level[v] == -1 && edge[i].flow > 0){level[v] = level[u]+1;Q.push(v);if(v == E)return 1;}}}return 0;}int Find(int now,int flow,int E){if(now == E)return flow;int os = flow;for(int i = head[now]; ~i; i = edge[i].next){int v = edge[i].to;if(level[v] == level[now]+1 && edge[i].flow>0){int temp = Find(v,min(flow,edge[i].flow),E);if(!temp){level[v] = -1;continue;}edge[i].flow -= temp;edge[i^1].flow += temp;flow -= temp;if(flow == 0)break;}}return os-flow;}void Dinic(int S,int E){int ans = 0;while(bfs(S,E)){int temp = Find(S,INF,E);ans += temp;}if(ans == n)puts("YES");elseputs("NO");}int val[1500];int main(){int x,num;while(~scanf("%d %d",&n,&m)){memset(head,-1,sizeof(head));memset(val,0,sizeof(val));cnt = num = 0;for(int i = 1; i <= n; i++){int temp = 0;for(int j = 0; j < m; j++){x = read();if(x)temp |= (1<<j);}if(!temp && val[temp] == 0)num++;val[temp]++;}int mmp = 0;for(int i = 1; i < (1<<m); i++){if(val[i]){mmp++;ADD(0,mmp,val[i]);for(int j = 0; j < m; j++){if(i & (1<<j))ADD(mmp,num+j+1,val[i]);}}}for(int i = 1; i <= m; i++){x = read();ADD(num+i,num+m+1,x);}Dinic(0,num+m+1);}return 0;}


原创粉丝点击