题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3081

推荐博客:https://www.cnblogs.com/liuxin13/p/4728131.html

这个题目没什么思路,完全不知道怎么写,后来看了题解,说是网络流+二分+并查集,然后更加懵了。

然后就z继续看了详细解答,才知道怎么去写。

emmm...这个题目他是让你求不同男孩女孩全部都成功配对最多会有多少轮,每一轮的女孩配对的男生都不一样。

还有一个让题目复杂一点的就是女孩子有朋友,在一个女孩圈里,她朋友没吵过架的男生在下一轮里可以成为她的男朋友。

先不考虑女孩子有女孩圈里,也不求最多有多少轮,就是男生女生要全部成功配对,那就是一个网络流的裸题。

但是呢,现在要求最多有多少轮(不考虑女孩圈),那其实也很难想到二分。。。

不过有人提示你用二分了,这个就觉得二分可以做,而且感觉也特别对,那就这样写吧,至于解释就是一般求最值都要想到用二分,

而且这个还是可以找到单调性,这个单调性就是如果最大流==n*x(x是被二分枚举的答案)那就说明这个可以是答案,当然也可以更大一点,所以就更新这个l=mid+1

不然就是这个mid大了,所以这个r就更新为mid-1。

最后就是考虑有女孩圈了,既然有女孩圈,是一个圈,那就容易想到并查集,所以这个题目的第三个算法就是并查集,

但是这个并查集怎么用,我开始也不知道,后来看了一点点别人写的代码才理解的,这个就是把一个把一个圈子的女孩的所有男朋友都连到根节点上去。

这个样子,以后每一个女孩找男朋友都可以通过根节点去连线(建图)

大致思路就是这个样子的,接下来敲代码了。

非常郁闷,又找了一个晚上的bug,唉,好伤心,好想哭。。。。

最后还是刷牙的时候感觉自己的问题,我这么写很可能会同一边输入很多次,这个需要判断一下,哭了。。。

  1. #include <cstdio>
  2. #include <cstdlib>
  3. #include <cstring>
  4. #include <iostream>
  5. #include <queue>
  6. #include <string>
  7. #include <algorithm>
  8. #define inf 0x3f3f3f3f
  9. using namespace std;
  10. const int INF = 0x3f3f3f3f;
  11. const int maxn = 1e5+;
  12.  
  13. struct edge
  14. {
  15. int u, v, c, f;
  16. edge(int u, int v, int c, int f) :u(u), v(v), c(c), f(f) {}
  17. };
  18. vector<edge>e;
  19. vector<int>G[maxn];
  20. int level[maxn];//BFS分层,表示每个点的层数
  21. int iter[maxn];//当前弧优化
  22. int m;
  23. void init()
  24. {
  25. for (int i = ; i <= maxn; i++)G[i].clear();
  26. e.clear();
  27. }
  28. void addedge(int u, int v, int c)
  29. {
  30. e.push_back(edge(u, v, c, ));
  31. e.push_back(edge(v, u, , ));
  32. m = e.size();
  33. G[u].push_back(m - );
  34. G[v].push_back(m - );
  35. }
  36. void BFS(int s)//预处理出level数组
  37. //直接BFS到每个点
  38. {
  39. memset(level, -, sizeof(level));
  40. queue<int>q;
  41. level[s] = ;
  42. q.push(s);
  43. while (!q.empty())
  44. {
  45. int u = q.front();
  46. q.pop();
  47. for (int v = ; v < G[u].size(); v++)
  48. {
  49. edge& now = e[G[u][v]];
  50. if (now.c > now.f && level[now.v] < )
  51. {
  52. level[now.v] = level[u] + ;
  53. q.push(now.v);
  54. }
  55. }
  56. }
  57. }
  58. int dfs(int u, int t, int f)//DFS寻找增广路
  59. {
  60. if (u == t)return f;//已经到达源点,返回流量f
  61. for (int &v = iter[u]; v < G[u].size(); v++)
  62. //这里用iter数组表示每个点目前的弧,这是为了防止在一次寻找增广路的时候,对一些边多次遍历
  63. //在每次找增广路的时候,数组要清空
  64. {
  65. edge &now = e[G[u][v]];
  66. if (now.c - now.f > && level[u] < level[now.v])
  67. //now.c - now.f > 0表示这条路还未满
  68. //level[u] < level[now.v]表示这条路是最短路,一定到达下一层,这就是Dinic算法的思想
  69. {
  70. int d = dfs(now.v, t, min(f, now.c - now.f));
  71. if (d > )
  72. {
  73. now.f += d;//正向边流量加d
  74. e[G[u][v] ^ ].f -= d;
  75. //反向边减d,此处在存储边的时候两条反向边可以通过^操作直接找到
  76. return d;
  77. }
  78. }
  79. }
  80. return ;
  81. }
  82. int Maxflow(int s, int t)
  83. {
  84. int flow = ;
  85. for (;;)
  86. {
  87. BFS(s);
  88. if (level[t] < )return flow;//残余网络中到达不了t,增广路不存在
  89. memset(iter, , sizeof(iter));//清空当前弧数组
  90. int f;//记录增广路的可增加的流量
  91. while ((f = dfs(s, t, INF)) > )
  92. {
  93. flow += f;
  94. }
  95. }
  96. return flow;
  97. }
  98.  
  99. int f[maxn], boy[maxn], girl[maxn];
  100. vector<int>love[maxn];
  101.  
  102. int findx(int x)
  103. {
  104. return f[x] == x ? x : f[x] = findx(f[x]);
  105. }
  106.  
  107. void unite(int x,int y)
  108. {
  109. x = findx(x);
  110. y = findx(y);
  111. if (x == y) return;
  112. f[x] = y;
  113. }
  114. int n;
  115. bool vis[][];
  116. void buildgrath(int flow,int s,int t)
  117. {
  118. init();
  119. memset(vis, , sizeof(vis));
  120. for(int i=;i<=n;i++)
  121. {
  122. if(!vis[s][i]) addedge(s, i, flow);
  123. if(!vis[i+n][t]) addedge(i + n, t, flow);
  124.  
  125. int u = findx(i);
  126. int len = love[u].size();
  127.  
  128. for(int j=;j<len;j++)
  129. {
  130. if (vis[i][love[u][j]]) continue;
  131. addedge(i, love[u][j], );
  132. vis[i][love[u][j]] = ;
  133. }
  134. }
  135. }
  136.  
  137. int main()
  138. {
  139. int w;
  140. scanf("%d", &w);
  141. while(w--)
  142. {
  143. int m, fx;
  144. scanf("%d%d%d", &n, &m, &fx);
  145. for (int i = ; i <= *n+; i++)
  146. {
  147. f[i] = i;
  148. love[i].clear();
  149. }
  150. for(int i=;i<=m;i++)
  151. {
  152. scanf("%d%d", &girl[i], &boy[i]);
  153. }
  154. for(int i=;i<=fx;i++)
  155. {
  156. int x, y;
  157. scanf("%d%d", &x, &y);
  158. unite(x, y);
  159. }
  160. int s = , t = n + n + ;
  161. int l = , r = n;
  162. for(int i=;i<=m;i++)
  163. {
  164. int u = findx(girl[i]);
  165. love[u].push_back(boy[i] + n);
  166. }
  167. int ans = ;
  168. while(l<=r)
  169. {
  170. int mid = (l + r) >> ;
  171. buildgrath(mid, s, t);
  172. int ex = Maxflow(s, t);
  173. if(ex==n*mid)
  174. {
  175. l = mid + ;
  176. ans = mid;
  177. }
  178. else r = mid - ;
  179. }
  180. printf("%d\n", ans);
  181. }
  182. return ;
  183. }

N - Marriage Match II 网络流的更多相关文章

  1. HDU 3081 Marriage Match II (网络流,最大流,二分,并查集)

    HDU 3081 Marriage Match II (网络流,最大流,二分,并查集) Description Presumably, you all have known the question ...

  2. HDU 3081 Marriage Match II 二分 + 网络流

    Marriage Match II 题意:有n个男生,n个女生,现在有 f 条男生女生是朋友的关系, 现在有 m 条女生女生是朋友的关系, 朋友的朋友是朋友,现在进行 k 轮游戏,每轮游戏都要男生和女 ...

  3. HDU 3081 Marriage Match II (二分图,并查集)

    HDU 3081 Marriage Match II (二分图,并查集) Description Presumably, you all have known the question of stab ...

  4. HDU3081:Marriage Match II (Floyd/并查集+二分图匹配/最大流(+二分))

    Marriage Match II Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others ...

  5. hdu3081 Marriage Match II(最大流)

    转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud Marriage Match II Time Limit: 2000/1000 M ...

  6. HDU 3081 Marriage Match II(二分法+最大流量)

    HDU 3081 Marriage Match II pid=3081" target="_blank" style="">题目链接 题意:n个 ...

  7. Marriage Match II(二分+并查集+最大流,好题)

    Marriage Match II http://acm.hdu.edu.cn/showproblem.php?pid=3081 Time Limit: 2000/1000 MS (Java/Othe ...

  8. HDU3081 Marriage Match II —— 传递闭包 + 二分图最大匹配 or 传递闭包 + 二分 + 最大流

    题目链接:https://vjudge.net/problem/HDU-3081 Marriage Match II Time Limit: 2000/1000 MS (Java/Others)    ...

  9. 【HDU3081】Marriage Match II (二分+最大流)

    Description Presumably, you all have known the question of stable marriage match. A girl will choose ...

随机推荐

  1. 2020不平凡的90天,Python分析三个月微博热搜数据带你回顾

    前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者:刘早起早起 PS:如有需要Python学习资料的小伙伴可以加点击下方链 ...

  2. SpringBoot连接Redis服务出现DENIED Redis is running in protected mode because protected mode is enabled

    修改redis.conf,yes 改为 no

  3. 【一起学设计模式】观察者模式实战:真实项目中屡试不爽的瓜娃EventBus到底如何实现观察者模式的?

    申明 本文章首发自本人公众号:壹枝花算不算浪漫,如若转载请标明来源! 感兴趣的小伙伴可关注个人公众号:壹枝花算不算浪漫 22.jpg 前言 之前出过一个设计模式的系列文章,这些文章和其他讲设计模式的文 ...

  4. pytorch 中的LSTM模块

  5. iconv 参数详解

    参数详解: $row [] = iconv('utf-8', 'GB2312//IGNORE', $value['message']); iconv ( string $in_charset , st ...

  6. ajax后台返回指定的错误码

    js: $.ajax({ type: "POST", url: 'post.php', data: serialNumber + "&getSerialNumbe ...

  7. [Windows] 如何用编程的方式格式化硬盘

    If memory serves, you're looking for SHFormatDrive(). Use the Format method of the Win32_Volume clas ...

  8. union 的概念及在嵌入式编程中的应用

    union 概念 union 在中文的叫法中又被称为共用体,联合或者联合体,它定义的方式与 struct 是相同的,但是意义却与 struct 完全不同,下面是 union 的定义格式: union ...

  9. Fabric的6大特性

    文章目录 什么是Hyperledger Fabric 1. 成员准入 2. 性能,可伸缩性和信任级别 3 需要了解的数据 4 通过不可变的分布式账本进行复杂查询 5 支持插件组件的模块化架构 6 保护 ...

  10. 深拷贝、浅拷贝与Cloneable接口

    深拷贝与浅拷贝 浅拷贝 public class Student implements Cloneable{ Integer a; Integer b; @Override protected Obj ...