题目大意:农夫FJ的农场有一批奶牛,奶牛有自己喜爱的food和drink,FJ要计划一个策略,使得让尽可能多的牛匹配自己喜欢的food和drink,每种food和drink只能被分配一次,每头奶牛只能选择一种food和drink
思路:因为不是两个对象之间的匹配,所以不是最大匹配。是多个源点和多个汇点问题,所以可建立超级源点和超级汇点,从而利用网络流求最大流。sap~~79ms撸过~~把cin改掉应该能0ms吧~~嘿嘿
为了满足每头牛一个food和一个drink,要把牛拆开,其中的连线容量为1,我的图:0---->food----->牛前------->牛后------->drink----->f+2*n+d+1
AC program: #include<iostream> #include<stdio.h> #include<string.h> #include<math.h> #include<queue> #include<algorithm> using namespace std; #define inf 1000000000 #define maxn 450 #define maxm 21000 //note!! 如果RE就是这里出的原因 int num;//note1 int n,f,d; struct node { int c,next,to; }e[maxm]; //note2 int box[maxn];//链式前向星 void addee(int u,int v,int w) { e[num].to=v; e[num].c=w; e[num].next=box[u]; box[u]=num++; } void init1() { int u,v; for(int i=1;i<=f;i++) { u=0;v=i; addee(u,v,1); addee(v,u,0); } } void init2() { int u,v; for(int i=f+2*n+1;i<=f+2*n+d;i++) { u=i;v=f+2*n+d+1; addee(u,v,1); addee(v,u,0); } } void init3() { int u,v; for(int i=f+1;i<=f+n;i++) { u=i;v=n+i; addee(u,v,1); addee(v,u,0); } } void init4(int p) { int ff,dd; cin>>ff>>dd; int food,drink; int u,v; while(ff--) { cin>>food; u=food; v=f+p; addee(u,v,1); addee(v,u,0); } while(dd--)/// { cin>>drink; u=f+n+p;v=f+n*2+drink; addee(u,v,1); addee(v,u,0); } } int sap(int start,int end,int nnn) { int numh[maxn],h[maxn],cur[maxn],pre[maxn]; int cur_flow,flow_ans=0,u,tmp,neck,i; memset(h,0,sizeof(h)); memset(numh,0,sizeof(numh));/// memset(pre,-1,sizeof(pre));/// for(int i=1;i<=nnn;i++) cur[i]=box[i]; numh[0]=nnn; u=start; while(h[start]<nnn) { if(u==end) { cur_flow=inf; for(i=start;i!=end;i=e[cur[i]].to) { if(cur_flow>e[cur[i]].c) { neck=i; cur_flow=e[cur[i]].c; } } for(i=start;i!=end;i=e[cur[i]].to) { tmp=cur[i]; e[tmp].c-=cur_flow; e[tmp^1].c+=cur_flow; } flow_ans+=cur_flow; u=neck; } for(i=cur[u];i!=-1;i=e[i].next) if(e[i].c&&h[u]==h[e[i].to]+1) break; if(i!=-1) { cur[u]=i; pre[e[i].to]=u; u=e[i].to; } else { if(0==--numh[h[u]])break; cur[u]=box[u]; for(tmp=nnn,i=box[u];i!=-1;i=e[i].next) if(e[i].c) tmp=min(tmp,h[e[i].to]); h[u]=tmp+1; ++numh[h[u]]; if(u!=start)u=pre[u]; } } return flow_ans; } int main() { while(cin>>n>>f>>d) { num=0; memset(box,-1,sizeof(box)); init1();//超级源点和food init2();//超级汇点和drink init3();//牛和牛自身 for(int i=1;i<=n;i++) { init4(i); //牛前和food,牛后和drink } int love; love=sap(0,f+n*2+d+1,f+n*2+d+2);//f+n*2+d+2个点 printf("%d\n",love); } //system("pause"); return 0;}