uva753 A Plug for UNIX

最大流。

流可以对应一种分配方式。

显然最大流就可以表示最多匹配数

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn = 500 + 10;
const int maxm = 100000 + 10;
const int maxl = 30;
const int inf = 0x3f3f3f3f;

char s[maxn][maxl],t[maxl],t2[maxl];
int g[maxn],v[maxm],nex[maxm],f[maxm],eid;
int id[maxn],vid;
int S,T;
int d[maxn],gap[maxn];
int n,m,k,a1,a2;

void addedge(int a,int b,int F) {
    v[eid]=b; f[eid]=F; nex[eid]=g[a]; g[a]=eid++;
    v[eid]=a; f[eid]=0; nex[eid]=g[b]; g[b]=eid++;
}

void build() {
    memset(g,-1,sizeof(g)); eid=0;
    vid=0;
    S=++vid; T=++vid;
    scanf("%d",&n);
    for(int i=1;i<=n;i++) {
        scanf("%s",s[i]);
        id[i]=0;
        for(int j=1;j<i;j++) if(strcmp(s[i],s[j])==0) {
            id[i]=id[j];
            break;    
        }
        if(!id[i]) id[i]=++vid;
        addedge(id[i],T,1);
        //printf("id[%d]=%d\n",i,id[i]);
    }
    scanf("%d",&m);
    for(int i=n+1;i<=n+m;i++) {
        scanf("%s",t);
        scanf("%s",s[i]);
        id[i]=0;
        for(int j=1;j<i;j++) if(strcmp(s[i],s[j])==0) {
            id[i]=id[j];
            break;    
        }
        if(!id[i]) id[i]=++vid;
        addedge(S,id[i],1);
        //printf("id[%d]=%d\n",i,id[i]);
    }
    scanf("%d",&k);
    for(int i=1;i<=k;i++) {
        scanf("%s",t);
        scanf("%s",t2);
        for(int j=1;j<=n+m;j++) if(strcmp(s[j],t)==0) {a1=id[j]; break;}
        for(int j=1;j<=n+m;j++) if(strcmp(s[j],t2)==0) {a2=id[j]; break;}
        addedge(a1,a2,inf);
        //printf("%d %d\n",a1,a2);
    }
}

int ISAP(int u,int flow) {
    if(u==T) return flow;
    int cur=0,aug,mindist=vid;
    
    for(int i=g[u];~i;i=nex[i]) 
        if(f[i] && d[v[i]]+1==d[u]) {
            aug=ISAP(v[i],min(flow-cur,f[i]));
            cur+=aug;
            f[i]-=aug;
            f[i^1]+=aug;
            if(cur==flow || d[S]>=vid) {
                return cur;    
            }
        }
    
    if(cur==0) {
        if(!--gap[d[u]]) {
            d[S]=vid;
            return cur;    
        }
        for(int i=g[u];~i;i=nex[i]) if(f[i]) 
            mindist=min(d[v[i]],mindist);
        ++gap[d[u]=mindist+1];                
    }
    return cur;
}

void solve() {
    memset(d,0,sizeof(d));
    memset(gap,0,sizeof(gap));
    int res=0;
    gap[0]=vid;
    while(d[S]<vid) {
        res+=ISAP(S,inf);
        
    } 
    printf("%d\n",m-res);
}


int main() {
    int T;
    scanf("%d",&T);
    while(T--) {
        build();
        solve();
        if(T) printf("\n");
    }
    return 0;
}
posted @ 2016-06-08 09:32  invoid  阅读(129)  评论(0编辑  收藏  举报