poj-3281(拆點+最大流)
阿新 • • 發佈:2018-11-15
題意:有n頭牛,f種食物,d種飲料,每頭牛有自己喜歡的食物和飲料,問你最多能夠幾頭牛搭配好,每種食物或者飲料只能一頭牛享用;
解題思路:把牛拆點,因為流過牛的流量是由限制的,只能為1,然後,食物和牛的入點相連,牛的出點和飲料相連,求解最大流
程式碼:
#include<iostream> #include<algorithm> #include<cstring> #include<cstdio> #include<queue> using namespace std; const int maxn=200500; const int inf=0x3f3f3f3f; struct Edge { int fa; int next; int to; int w; }edge[maxn]; int n,m,f,d; int head[maxn]; int cnt,Start,End; int x,y,w; int depth[maxn]; void add(int u,int v,int w) { //cout<<u<<" "<<v<<endl; edge[cnt].next=head[u];edge[cnt].fa=u; edge[cnt].to=v;edge[cnt].w=w;head[u]=cnt++; edge[cnt].next=head[v];edge[cnt].fa=v; edge[cnt].to=u;edge[cnt].w=0;head[v]=cnt++; } bool bfs()//分層; { memset(depth,0,sizeof(depth)); queue<int>q; q.push(Start); depth[Start]=1; while(!q.empty()) { int temp=q.front(); q.pop(); for(int i=head[temp];i!=-1;i=edge[i].next) { int v=edge[i].to; if(depth[v]||edge[i].w<=0) continue; depth[v]=depth[temp]+1; q.push(v); } } return depth[End];//若為0表示沒法到達也就是沒有路徑了; } int dfs(int u,int maxflow) { if(u==End) return maxflow; int add=0; for(int i=head[u];i!=-1&&add<maxflow;i=edge[i].next) { int v=edge[i].to; if(depth[v]!=depth[u]+1) continue; if(edge[i].w==0) continue; int tempflow=dfs(v,min(edge[i].w,maxflow-add)); edge[i].w-=tempflow; edge[i^1].w+=tempflow; add+=tempflow; } return add; } int dinic() { int ans=0; while(bfs()) { ans+=dfs(Start,0x3f3f3f3f); } return ans; } int main() { int tmp; memset(head,-1,sizeof(head)); scanf("%d%d%d",&n,&f,&d); Start=0;End=2*n+f+d+1; for(int i=1;i<=n;i++) add(i,i+n,1); for(int i=2*n+1;i<=2*n+f;i++) add(Start,i,1); for(int i=2*n+f+1;i<=2*n+f+d;i++) add(i,End,1); for(int i=1;i<=n;i++) { scanf("%d%d",&x,&y); for(int j=1;j<=x;j++) { scanf("%d",&tmp); add(tmp+2*n,i,1); } for(int j=1;j<=y;j++) { scanf("%d",&tmp); add(i+n,tmp+2*n+f,1); } } int ans=dinic(); printf("%d\n",ans); }