HDU3605 Escape (最大流+缩点)
2012如果这是世界末日怎么办?我不知道怎么做。但现在科学家们发现,有些恒星可以生存,但有些人却不适合生活在一些星球上。现在科学家们需要你的帮助,就是确定所有的人都能在这些星球上生活。
输入
多组测试数据,每个数据的开头是n(1<=n<=10万),m(1<=m<=10)n表示地球上有n个人,m代表m星球,行星和人的标签都是从0开始的。这里有n行,每行代表一个适合居住的人,每行有m个数字,第i个数字是1,表示一个人适合居住在第i个星球,或者是0,表示这个人不适合居住在第i个星球。
最后一行有m个数字,第i个数字ai表示第i个星球最多能容纳ai人。。
0<=ai<=100000
输出
决定是否所有的人都能不辜负这些明星
如果可以输出YES,否则输出NO。
点数很多,但是考虑到每个人只有1000种选择方案,可以缩点后跑网络流,时间复杂度是合理的。
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn=2e5+100; const ll inf=1e18; int n,m; struct node { int u,v,nxt; ll w; }edge[maxn<<1]; int head[maxn],tot; void addedge (int u,int v,ll w) { edge[tot].u=u; edge[tot].v=v; edge[tot].w=w; edge[tot].nxt=head[u]; head[u]=tot++; edge[tot].u=v; edge[tot].v=u; edge[tot].w=0; edge[tot].nxt=head[v]; head[v]=tot++; } ll dep[maxn],inq[maxn],cur[maxn],wjm,maxflow,s,t; bool bfs () { for (int i=0;i<=t;i++) { cur[i]=head[i]; dep[i]=inf; inq[i]=0; } dep[s]=0; queue<int> q; q.push(s); while (q.size()) { int u=q.front(); q.pop(); inq[u]=0; for (int i=head[u];i!=-1;i=edge[i].nxt) { int v=edge[i].v; if (dep[v]>dep[u]+1&&edge[i].w) { dep[v]=dep[u]+1; if (inq[v]==0) { q.push(v); inq[v]=1; } } } } if (dep[t]!=inf) return 1; return 0; } ll dfs (int u,ll flow) { ll increase=0; if (u==t) { wjm=1; maxflow+=flow; return flow; } ll used=0; for (int i=cur[u];i!=-1;i=edge[i].nxt) { cur[u]=i; int v=edge[i].v; if (edge[i].w&&dep[v]==dep[u]+1) { if (increase=dfs(v,min(flow-used,edge[i].w))) { used+=increase; edge[i].w-=increase; edge[i^1].w+=increase; if (used==flow) break; } } } return used; } ll Dinic () { while (bfs()) { wjm=1; while (wjm==1) { wjm=0; dfs(s,inf); } } return maxflow; } int main () { // 源点为0 // 1~n为人 // n+1~n+m为行星 // n+m+1为汇点 // 源点向每个人连一条容量为1的边 // 每个人向可以居住的行星连一条容量为1的边 // 每个行星向汇点连一条容量为a(i)的边 while (~scanf("%d%d",&n,&m)) { map<vector<int> ,int> mp; for (int i=1;i<=n;i++) { vector<int> tt; for (int j=1;j<=m;j++) { int x; scanf("%d",&x); tt.push_back(x); } mp[tt]++; } s=0; t=mp.size()+m+1; for (int i=0;i<=t;i++) head[i]=-1;tot=0;wjm=0;maxflow=0; int cnt=0; for (auto it=mp.begin();it!=mp.end();it++) { cnt++; addedge(s,cnt,it->second); vector<int> tt=it->first; for (int i=0;i<tt.size();i++) if (tt[i]==1) addedge(cnt,mp.size()+i+1,it->second); } for (int i=1;i<=m;i++) { ll x; scanf("%lld",&x); addedge(mp.size()+i,t,x); } // printf("%lld\n",Dinic()); if (Dinic()==n) printf("YES\n"); else printf("NO\n"); } }