POJ3281_Dining
有一些饮料和食物,每种一个,每个客人喜欢一些饮料和一些食物,每个客人可以选择一种饮料和一种食物,问最多能够同时满足多少个客人同时拥有饮料和食物。
这样的,源点连接饮料,汇点连接食物,中间人分别连接饮料和食物。
然后这样直接跑最大流。。。。。是错的。
因为没有保证每个人只拿一种饮料和一种食物。
还需要对每个人拆点,保证每人所拥有的饮料和食物都不超过1,最终最大流就是最多能够满足条件的人数了。
召唤代码君:
#include <iostream> #include <cstdio> #include <cstring> #define maxn 5550 #define maxm 555550 using namespace std; int to[maxm],next[maxm],c[maxm],first[maxn],edge; int d[maxn],tag[maxn],TAG=520; int Q[maxn],bot,top; bool can[maxn]; int N,F,D,s,t,ans; void _init() { s=0,t=N+N+F+D+1,edge=-1; for (int i=s; i<=t; i++) first[i]=-1; } void addedge(int U,int V) { edge++; to[edge]=V,c[edge]=1,next[edge]=first[U],first[U]=edge; edge++; to[edge]=U,c[edge]=0,next[edge]=first[V],first[V]=edge; } void _input() { for (int i=1; i<=N; i++) addedge(F+i,F+N+D+i); for (int i=1; i<=F; i++) addedge(s,i); for (int i=1; i<=D; i++) addedge(F+N+i,t); int food,drink,tmp; for (int i=1; i<=N; i++) { scanf("%d%d",&food,&drink); while (food--) { scanf("%d",&tmp); addedge(tmp,F+i); } while (drink--) { scanf("%d",&tmp); addedge(F+N+D+i,F+N+tmp); } } } bool bfs() { Q[bot=top=1]=t,d[t]=0,tag[t]=++TAG,can[t]=false; while (bot<=top) { int cur=Q[bot++]; for (int i=first[cur]; i!=-1; i=next[i]) if (c[i^1]>0 && tag[to[i]]!=TAG) { tag[to[i]]=TAG,d[to[i]]=d[cur]+1; can[to[i]]=false,Q[++top]=to[i]; if (to[i]==s) return true; } } return false; } int dfs(int cur,int num) { if (cur==t) return num; int tmp=num,k; for (int i=first[cur]; i!=-1; i=next[i]) if (c[i]>0 && tag[to[i]]==TAG && d[to[i]]==d[cur]-1 && !can[to[i]]) { k=dfs(to[i],min(num,c[i])); if (k) num-=k,c[i]-=k,c[i^1]+=k; if (num==0) break; } if (num) can[cur]=true; return tmp-num; } int main() { while (scanf("%d%d%d",&N,&F,&D)!=EOF) { _init(); _input(); for (ans=0; bfs(); ) ans+=dfs(s,111); printf("%d\n",ans); } return 0; }
如有转载,请注明出处(http://www.cnblogs.com/lochan)