题目大意:农夫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;}