题意:现在有包括了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;
}

 

It is your time to fight!