博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
HDU 3081 最大流+并查集
阅读量:5228 次
发布时间:2019-06-14

本文共 3255 字,大约阅读时间需要 10 分钟。

题意:有n个男生和n个女生,玩结婚游戏,由女生选择男生;女生可以选择不会和她吵架的男生以及不会和她闺蜜吵架的男生,闺蜜的闺蜜也是闺蜜。问你最多可以进行多少轮,每一轮每个女生只能选择一个之前她没选过的男生。

思路:显然最少进行0轮,最多进行n轮,所以我们可以对轮数进行二分;源点到女生连一条容量为轮数的边,女生到她可选择的男生之间连一条容量为1的边,男生到汇点同样连一条容量为轮数的边,然后跑最大流判断是否满流。找到最大的轮数。要注意的是,每次跑最大流的时候都要重新建图。至于闺蜜的问题用一个并查集就可以了。

代码:

1 #include
2 #include
3 #define min(x,y) (x)<(y)?(x):(y) 4 const int N=222,M=N*N,INF=0x3f3f3f3f; 5 int n,l,r,s,t; 6 int c[N][N],tmpc[N][N]; 7 int fa[N]; 8 int h[N],gap[N]; 9 int find(int a) 10 { 11 if(fa[a]!=a) return fa[a]=find(fa[a]); 12 return a; 13 } 14 void union_(int a,int b) 15 { 16 a=find(a),b=find(b); 17 if(a!=b) fa[a]=b; 18 } 19 int dfs(int u,int flow) 20 { 21 if(u==t) return flow; 22 int a,v,cc=flow,minh=t; 23 for(v=1;v<=t;v++) 24 { 25 if(c[u][v]) 26 { 27 if(h[v]==h[u]-1) 28 { 29 a=min(c[u][v],flow); 30 a=dfs(v,a); 31 c[u][v]-=a; 32 cc-=a; 33 c[v][u]+=a; 34 if(h[s]>t) return flow-cc; 35 if(!cc) break; 36 } 37 minh=min(minh,h[v]); 38 } 39 } 40 if(cc==flow) 41 { 42 if(--gap[h[u]]==0) h[s]=t+1; 43 ++gap[h[u]=minh+1]; 44 } 45 return flow-cc; 46 } 47 int isap() 48 { 49 memset(gap,0,sizeof(gap)); 50 memset(h,0,sizeof(h)); 51 int ans=0;gap[0]=t+1; 52 while(h[s]<=t) 53 ans+=dfs(s,INF); 54 return ans; 55 } 56 int bin() 57 { 58 int l=0,r=n,mid,i,j,ans; 59 while(l<=r) 60 { 61 mid=(l+r)>>1; 62 for(i=1;i<=n;i++) 63 c[s][i]=mid,c[i+n][t]=mid; 64 for(i=1;i<=n;i++) 65 for(j=n+1;j<=n+n;j++) 66 c[i][j]=tmpc[i][j]; 67 if(mid*n==isap()) 68 { 69 ans=mid; 70 l=mid+1; 71 } 72 else 73 r=mid-1; 74 } 75 return ans; 76 } 77 int main() 78 { 79 int T,m,k,i,j,x,y; 80 scanf("%d",&T); 81 while(T--) 82 { 83 scanf("%d%d%d",&n,&m,&k); 84 memset(c,0,sizeof(c)); 85 s=0,t=n*2+1; 86 for(i=1;i<=n;i++) 87 fa[i]=i; 88 while(m--) 89 { 90 scanf("%d%d",&x,&y); 91 c[x][y+n]=1; 92 } 93 while(k--) 94 { 95 scanf("%d%d",&x,&y); 96 union_(x,y); 97 for(i=1;i<=n;i++) 98 { 99 if(find(i)==find(x))100 {101 for(j=n+1;j<=n+n;j++)102 {103 if(c[i][j]&&!c[x][j])104 c[x][j]=1;105 }106 }107 if(find(i)==find(y))108 {109 for(j=n+1;j<=n+n;j++)110 {111 if(c[i][j]&&!c[y][j])112 c[y][j]=1;113 }114 }115 }116 }117 for(i=1;i<=n;i++) for(j=n+1;j<=n+n;j++) tmpc[i][j]=c[i][j];118 printf("%d\n",bin());119 }120 return 0;121 }
View Code

 

转载于:https://www.cnblogs.com/L-King/p/5349653.html

你可能感兴趣的文章
Apache Common-IO 使用
查看>>
javaScript数组去重方法汇总
查看>>
评价意见整合
查看>>
二、create-react-app自定义配置
查看>>
Android PullToRefreshExpandableListView的点击事件
查看>>
系统的横向结构(AOP)
查看>>
linux常用命令
查看>>
NHibernate.3.0.Cookbook第四章第6节的翻译
查看>>
使用shared memory 计算矩阵乘法 (其实并没有加速多少)
查看>>
Django 相关
查看>>
git init
查看>>
训练记录
查看>>
IList和DataSet性能差别 转自 http://blog.csdn.net/ilovemsdn/article/details/2954335
查看>>
Hive教程(1)
查看>>
第16周总结
查看>>
C#编程时应注意的性能处理
查看>>
Fragment
查看>>
比较安全的获取站点更目录
查看>>
苹果开发者账号那些事儿(二)
查看>>
使用C#交互快速生成代码!
查看>>