题目大意:n个男孩n个女孩,女孩选男孩,每个女孩都要选到不同的人k对女孩有相同选择标准,女孩每轮都选择没选过的男孩,问总共能选几轮。
解题思路:
女孩编号1......n,男孩编号n+1,n+2,......,2*n
由女孩到男孩建立容量为1的边,女孩的朋友与自己的男友也建立容量为1的边。
判断是否是女孩的朋友可以用并查集,朋友的朋友具有传递性,如果两人有共同父节点,那么就是朋友。
可以用二分长度去判断最多进行的轮数,源点向女孩建立容量为mid的边,同样,男孩向汇点建立容量为mid的边。
AC:
#include <iostream> #include <cstring> #include <cstdio> #include<algorithm> #define MAXN 210 #define MAXM 50000 struct node { int u,v,w; }; struct node2 { int x,y; }; node2 ee[MAXM]; int first[210],p[MAXN]; node e[MAXM]; int next[MAXM],cc,n,m,f; int gap[210],d[210],curedges[210],pre[210]; int map[105][105]; void add_edge(int u,int v,int w) { e[cc].u=u; e[cc].v=v; e[cc].w=w; next[cc]=first[u]; first[u]=cc; cc++; e[cc].u=v; e[cc].v=u; e[cc].w=0; next[cc]=first[v]; first[v]=cc; cc++; } void make_set(int n) { int i; for(i=0;i<=n;i++) p[i]=i; } int find_set(int i) { int j=i; while(j!=p[j]) j=p[j]; return p[i]=j; } int Union(int x,int y) { x=find_set(x); y=find_set(y); if(x==y) return 0; else { p[x]=y; return 1; } } void build(int t,int mid) { cc=0; int i,j; memset(map,0,sizeof(map)); memset(first,-1,sizeof(first)); memset(next,-1,sizeof(next)); for(i=1;i<=n;i++) { add_edge(0,i,mid); add_edge(n+i,t,mid); } for(i=0;i<m;i++) { int u=ee[i].x; int v=ee[i].y; for(j=1;j<=n;j++) { if(find_set(u)==find_set(j)) if(!map[j][v]) { map[j][v]=1; add_edge(j,n+v,1); } } } } int sap(int s,int t) { int cur_flow,flow_ans=0,u,tmp,neck,i; memset(d,0,sizeof(d)); memset(gap,0,sizeof(gap)); memset(pre,-1,sizeof(sizeof(pre))); for(i=0;i<=t;i++) curedges[i]=first[i]; gap[0]=t+1; u=s; while(d[s]<t+1) { if(u==t) { cur_flow=99999999; for(i=s;i!=t;i=e[curedges[i]].v) { if(cur_flow>e[curedges[i]].w) { neck=i; cur_flow=e[curedges[i]].w; } } for(i=s;i!=t;i=e[curedges[i]].v) { tmp=curedges[i]; e[tmp].w-=cur_flow; e[tmp^1].w+=cur_flow; } flow_ans+=cur_flow; u=neck; } for(i=curedges[u];i!=-1;i=next[i]) if(e[i].w&&d[u]==d[e[i].v]+1) break; if(i!=-1) { curedges[u]=i; pre[e[i].v]=u; u=e[i].v; } else { if(0==--gap[d[u]]) break; curedges[u]=first[u]; for(tmp=t+1,i=first[u];i!=-1;i=next[i]) if(e[i].w) tmp=std::min(tmp,d[e[i].v]); d[u]=tmp+1; ++gap[d[u]]; if(u!=s) u=pre[u]; } } return flow_ans; } int main() { int T; scanf("%d",&T); while(T--) { memset(ee,0,sizeof(ee)); memset(e,0,sizeof(e)); scanf("%d%d%d",&n,&m,&f); int i,s=0,t=n*2+1; for(i=0;i<m;i++) scanf("%d%d",&ee[i].x,&ee[i].y); make_set(t); for(i=0;i<f;i++) { int u,v; scanf("%d%d",&u,&v); Union(u,v); } int l=0,r=n,ans=0; while(l<=r) { int mid=(l+r)>>1; build(t,mid); int res=sap(s,t); if(res>=mid*n) { ans=mid; l=mid+1; } else r=mid-1; } printf("%d\n",ans); } return 0; }