标签:
最大流。
流可以对应一种分配方式。
显然最大流就可以表示最多匹配数
#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; }
标签:
原文地址:http://www.cnblogs.com/invoid/p/5569045.html