POJ3281 Dining
题目:http://poj.org/problem?id=3281
网络最大流近似模板。
因为同时要有牛和食物和饮料才能满足,故把牛、食物、饮料串在一条链上即可。
然而自己却一开始忘记将牛拆成两个点,连一条容量为1的边!
这是为了限制“一头牛只能吃一份食物饮料”这个条件。因为一头牛可以喜欢多个食物饮料。
#include<iostream> #include<cstdio> #include<cstring> #include<queue> using namespace std; const int INF=105; int f,d,n,head[405],fi,di,x,xnt=1,cur[405],mxflow,t; int dfn[405]; struct Edge{ int next,to,cap; Edge(int n=0,int t=0,int c=0):next(n),to(t),cap(c) {} }edge[40605]; queue<int> q; void add(int a,int b) { edge[++xnt]=Edge(head[a],b,1);head[a]=xnt; edge[++xnt]=Edge(head[b],a,0);head[b]=xnt; } bool bfs() { memset(dfn,0,sizeof dfn); while(q.size())q.pop(); dfn[0]=1;q.push(0); while(q.size()) { int k=q.front();q.pop(); for(int i=head[k],v;i;i=edge[i].next) if(!dfn[v=edge[i].to]&&edge[i].cap) { dfn[v]=dfn[k]+1; q.push(v); if(v==t)break; } } return dfn[t]; } int dfs(int k,int flow) { if(k==t)return flow; int used=0; for(int& i=cur[k],v;i;i=edge[i].next) if(dfn[v=edge[i].to]==dfn[k]+1&&edge[i].cap) { int tmp=dfs(v,min(edge[i].cap,flow-used)); if(!tmp)dfn[v]=0; edge[i].cap-=tmp; edge[i^1].cap+=tmp; used+=tmp; if(used==flow)break; } return used; } int main() { scanf("%d%d%d",&n,&f,&d); t=f+d+n+n+1; for(int i=1;i<=n;i++) { scanf("%d%d",&fi,&di); for(int j=1;j<=fi;j++) { scanf("%d",&x); add(x,i+f); } for(int j=1;j<=di;j++) { scanf("%d",&x); add(i+n+f,f+n+n+x); } } for(int i=1+f;i<=n+f;i++)add(i,i+n); for(int i=1;i<=f;i++)add(0,i); for(int i=n+n+f+1;i<t;i++)add(i,t); while(bfs()) { memcpy(cur,head,sizeof head); mxflow+=dfs(0,INF); } printf("%d",mxflow); return 0; }