hdu 3081(二分+最大流+并查集)
来源:互联网 发布:外交官 新秀丽 知乎 编辑:程序博客网 时间:2024/05/21 09:43
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3081
思路设源点为0,汇点为2*n+1,对没吵过架的女生和男生连容量为1的边(这里要用到并查集,每个女生的朋友也可以和该男生连边),然后就是源点与女生连边,容量为mid(0<=mid<=n),男生与汇点也连容量为mid的边(这里的mid即为为每个男孩和女孩找到了k个不同的伴侣,说明游戏可以进行k轮,附上链接:http://blog.csdn.net/qq564690377/article/details/7857983),然后就是二分搜索了。
View Code
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 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]<NV){ 54 for(v=1;v<=vt;v++){ 55 if(map[u][v]&&level[u]==level[v]+1){ 56 break; 57 } 58 } 59 if(v<=vt){ 60 pre[v]=u; 61 u=v; 62 if(v==vt){ 63 aug=inf; 64 for(int i=v;i!=vs;i=pre[i]){ 65 if(aug>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
0 0
- hdu 3081(二分+最大流+并查集)
- ★ HDU 3081 二分+最大流+并查集
- HDU 3081 并查集 二分枚举 最大流
- hdu 3277(最大流+二分+并查集)
- hdu 3081 Marriage Match II(二分最大流+并查集+判断满流)
- HDU 3081Marriage Match II(二分+并查集+网络流之最大流)
- hdu 3081 Marriage Match II(最大流 + 二分 + 并查集)
- hdu 3081 Marriage Match II (二分+最大流+并查集)
- HDU-3081-Marriage Match II(最大流+并查集+二分)
- hdu 3081 Marriage Match II(二分, 并查集,最大流)
- HDU - 3081 Marriage Match II(最大流+并查集+二分查找)
- hdu 3277 (二分+并查+最大流)
- hdu 3081(并查集+最大流)
- HDU 3081 Marriage Match II(二分+并查集+最大流)
- HDU 3081 Marriage Match II [二分最大流]+并查集?807★
- HDU 3081 Marriage Match II(二分+并查集+最大流)
- hdu 3081 Marriage Match II【并查集+二分+最大流Dinic+建图】
- HDU 3081 Marriage Match II(二分+并查集+最大流)
- dubbo小教程
- hdu 2883(最大流、判满流)
- hdu 2553(N皇后)
- hdu 3605(多重匹配)
- cf5c
- hdu 3081(二分+最大流+并查集)
- hdu 3277(最大流+二分+并查集)
- hdu 3416(最短路+最大流)
- hdu 4143
- hdu 3998(最长上升子序列及个数)
- hdu 4309(最大流+枚举状态)
- hdu 3046(最小割)
- hdu 1565+hdu 1569(最大点权独立集)
- win8下安装锐捷的兼容性问题