题目链接:
思路设源点为0,汇点为2*n+1,对没吵过架的女生和男生连容量为1的边(这里要用到并查集,每个女生的朋友也可以和该男生连边),然后就是源点与女生连边,容量为mid(0<=mid<=n),男生与汇点也连容量为mid的边(这里的mid即为为每个男孩和女孩找到了k个不同的伴侣,说明游戏可以进行k轮,附上链接:),然后就是二分搜索了。
View Code
1 #include2 #include 3 #include 4 using namespace std; 5 #define MAXN 222 6 #define inf 1<<30 7 int map[MAXN][MAXN]; 8 int mm[MAXN][MAXN]; 9 int pre[MAXN]; 10 int level[MAXN]; 11 int gap[MAXN]; 12 int parent[MAXN]; 13 int NV,n,m,f; 14 15 void Initiate(){ 16 for(int i=1;i<=2*n;i++){ 17 parent[i]=-1; 18 } 19 } 20 21 int Find(int x){ 22 int s; 23 for(s=x;parent[s]>0;s=parent[s]) 24 ; 25 while(x!=s){ 26 int tmp=parent[x]; 27 parent[x]=s; 28 x=tmp; 29 } 30 return s; 31 } 32 33 void Union(int u,int v){ 34 int r1=Find(u); 35 int r2=Find(v); 36 if(r1==r2)return ; 37 if(parent[r1]>parent[r2]){ 38 parent[r2]+=parent[r1]; 39 parent[r1]=r2; 40 }else { 41 parent[r1]+=parent[r2]; 42 parent[r2]=r1; 43 } 44 } 45 46 47 int SAP(int vs,int vt){ 48 memset(pre,-1,sizeof(pre)); 49 memset(level,0,sizeof(level)); 50 memset(gap,0,sizeof(gap)); 51 int v,u=pre[vs]=vs,maxflow=0,aug=inf; 52 gap[0]=NV; 53 while(level[vs] map[pre[i]][i])aug=map[pre[i]][i]; 66 } 67 maxflow+=aug; 68 for(int i=v;i!=vs;i=pre[i]){ 69 map[pre[i]][i]-=aug; 70 map[i][pre[i]]+=aug; 71 } 72 u=vs; 73 } 74 }else { 75 int minlevel=NV; 76 for(int v=1;v<=vt;v++){ 77 if(map[u][v]&&minlevel>level[v]){ 78 minlevel=level[v]; 79 } 80 } 81 gap[level[u]]--; 82 if(gap[level[u]]==0)break; 83 level[u]=minlevel+1; 84 gap[level[u]]++; 85 u=pre[u]; 86 } 87 } 88 return maxflow; 89 } 90 91 void Build(int k){ 92 memset(map,0,sizeof(map)); 93 for(int i=1;i<=n;i++){ 94 map[0][i]=k; 95 map[i+n][2*n+1]=k; 96 } 97 for(int i=1;i<=n;i++){ 98 for(int j=n+1;j<=2*n;j++){ 99 map[i][j]=mm[i][j];100 }101 }102 for(int i=1;i<=n;i++){103 for(int j=1;j<=n;j++){104 if(Find(i)==Find(j)){105 for(int k=n+1;k<=2*n;k++){106 if(map[i][k])map[j][k]=1;107 }108 }109 }110 }111 }112 113 114 int Binary_Search(){115 int low=0,high=n,tmp;116 NV=2*n+2;117 while(low<=high){118 int mid=(low+high)/2;119 Build(mid);120 if(mid*n==SAP(0,2*n+1)){121 tmp=mid;//这里需要保留mid值。122 low=mid+1;123 }else 124 high=mid-1;125 }126 return tmp;127 }128 129 130 int main(){131 int _case,g,b,g1,g2;132 scanf("%d",&_case);133 while(_case--){134 scanf("%d%d%d",&n,&m,&f);135 Initiate();136 memset(map,0,sizeof(map));137 memset(mm,0,sizeof(mm));138 for(int i=1;i<=m;i++){139 scanf("%d%d",&g,&b);140 map[g][b+n]=1;141 mm[g][b+n]=1;//保留原图,因为每次SAP之后,图就改变了。142 }143 for(int i=1;i<=f;i++){144 scanf("%d%d",&g1,&g2);145 if(Find(g1)!=Find(g2)){146 Union(g1,g2);147 }148 }149 int ans=Binary_Search();150 printf("%d\n",ans);151 }152 return 0;153 }154 155 156 157 158 159