题意:现在有包括了Bob在内的N个小朋友,M种游戏卡片,Bob可以和其他人交换卡片,除了Bob,每个人的交换原则都是只给出自己拥有大于1的卡片,接受自己没有的卡片。问他最多有多少不同的卡片。 N<=10; M<=25;
思路:最大流,卡片流向玩家表示Bob付出卡片,玩家流向卡片,边数玩家给Bob卡片,那么最后求最大流即可。
(这道题把流变成了交换,是个不错的模型。
#include<bits/stdc++.h> #define rep(i,a,b) for(int i=a;i<=b;i++) using namespace std; const int maxn=1000; const int inf=1000000; int S,T,Laxt[maxn],Next[maxn],To[maxn],Cap[maxn],cnt,num[26]; int dis[maxn],vd[maxn]; void add(int u,int v,int c) { Next[++cnt]=Laxt[u]; Laxt[u]=cnt; To[cnt]=v; Cap[cnt]=c; Next[++cnt]=Laxt[v]; Laxt[v]=cnt; To[cnt]=u; Cap[cnt]=0; } int sap(int u,int flow) { if(u==T||flow==0) return flow; int tmp,delta=0; for(int i=Laxt[u];i;i=Next[i]){ int v=To[i]; if(dis[u]==dis[v]+1&&Cap[i]){ tmp=sap(v,min(Cap[i],flow-delta)); Cap[i]-=tmp; Cap[i^1]+=tmp; delta+=tmp; if(dis[S]>=T||delta==flow) return delta; } } vd[dis[u]]--; if(!vd[dis[u]]) dis[S]=T; vd[++dis[u]]++; return delta; } void init() { cnt=1; rep(i,S,T) Laxt[i]=dis[i]=vd[i]=0; } int main() { int C,Case=0,N,M,tot,x; scanf("%d",&C); while(C--){ scanf("%d%d",&N,&M); S=0; T=N+M+1; init(); memset(num,0,sizeof(num)); scanf("%d",&tot); rep(i,1,tot) scanf("%d",&x),num[x]++; rep(i,1,M) add(S,i,num[i]); rep(i,2,N){ memset(num,0,sizeof(num)); scanf("%d",&tot); rep(j,1,tot) scanf("%d",&x),num[x]++; rep(j,1,M) if(!num[j]) add(j,M+i,1); else add(M+i,j,num[j]-1); } rep(i,1,M) add(i,T,1); int ans=0; while(dis[S]<T) ans+=sap(S,inf); printf("Case #%d: %d\n",++Case,ans); } return 0; }