由于无法直接将果汁和饮料连边,所以将人放在中间,果汁和饮料放在两侧,然后分别向对应的人连边。同时,为了保证每一个人只被算一次,对每一个人裂点,两个点中间连一条流量为1的边。
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 505 4 #define inf 0x3f3f3f3f 5 struct ji{ 6 int nex,to,len; 7 }edge[N*N]; 8 queue<int>q; 9 int E,n,x,y,k1,k2,p,d[N],head[N],work[N]; 10 void add(int x,int y,int z){ 11 edge[E].nex=head[x]; 12 edge[E].to=y; 13 edge[E].len=z; 14 head[x]=E++; 15 if (E&1)add(y,x,0); 16 } 17 bool bfs(){ 18 q.push(0); 19 memset(d,-1,sizeof(d)); 20 d[0]=0; 21 while (!q.empty()){ 22 int k=q.front(); 23 q.pop(); 24 for(int i=head[k];i!=-1;i=edge[i].nex) 25 if ((edge[i].len)&&(d[edge[i].to]<0)){ 26 d[edge[i].to]=d[k]+1; 27 q.push(edge[i].to); 28 } 29 } 30 return d[n]>=0; 31 } 32 int dfs(int k,int s){ 33 if (k==n)return s; 34 int p; 35 for(int &i=work[k];i!=-1;i=edge[i].nex) 36 if ((edge[i].len)&&(d[edge[i].to]==d[k]+1)){ 37 p=dfs(edge[i].to,min(s,edge[i].len)); 38 if (p){ 39 edge[i].len-=p; 40 edge[i^1].len+=p; 41 return p; 42 } 43 } 44 return 0; 45 } 46 int dinic(){ 47 int k,ans=0; 48 while (bfs()){ 49 memcpy(work,head,sizeof(work)); 50 while (k=dfs(0,inf))ans+=k; 51 } 52 return ans; 53 } 54 int main(){ 55 scanf("%d%d%d",&n,&x,&y); 56 memset(head,-1,sizeof(head)); 57 for(int i=1;i<=x;i++)add(0,i,1); 58 for(int i=1;i<=n;i++){ 59 scanf("%d%d",&k1,&k2); 60 for(int j=1;j<=k1;j++){ 61 scanf("%d",&p); 62 add(p,x+i,1); 63 } 64 add(x+i,n+x+i,1); 65 for(int j=1;j<=k2;j++){ 66 scanf("%d",&p); 67 add(n+x+i,2*n+x+p,1); 68 } 69 } 70 n=2*n+x; 71 for(int i=n+1;i<=n+y;i++)add(i,n+y+1,1); 72 n+=y+1; 73 printf("%d",dinic()); 74 }