原题链接

http://acm.hdu.edu.cn/showproblem.php?pid=4975

这是一道很裸的最大流,将每个点(i,j)看作是从Ri向Cj的一条容量为9的边,从源点除法连接每个Ri,再从每个Ci连接至汇点。如若最大流不是滿流,则问题无解。这道题的关键就是在于如何判断是否有多解。考虑这样一个事实,若残余网络上有多个点构成一个环,那么流量可在这个环上调整,某条边上多余的流量可以被环上的其他的边弥补回来。所以如果残余网络上存在一个边数大于2的环,那么问题则是多解。我判断是否有环的方法是Tarjan。

详见代码:

  1. #include<iostream>
  2. #include<stack>
  3. #include<vector>
  4. #include<cstring>
  5. #include<algorithm>
  6. #include<queue>
  7. #define MAX_V 2015
  8. #define MAX_N 10004
  9. #define INF 2500005
  10. using namespace std;
  11.  
  12. struct edge{int to,cap,rev;};
  13.  
  14. vector<edge> G[MAX_N];
  15. int level[MAX_V];
  16. int iter[MAX_V];
  17.  
  18. void add_edge(int from,int to,int cap) {
  19. G[from].push_back((edge) {to, cap, G[to].size()});
  20. G[to].push_back((edge) {from, , G[from].size() - });
  21. }
  22.  
  23. void bfs(int s) {
  24. memset(level, -, sizeof(level));
  25. queue<int> que;
  26. level[s] = ;
  27. que.push(s);
  28. while (!que.empty()) {
  29. int v = que.front();
  30. que.pop();
  31. for (int i = ; i < G[v].size(); i++) {
  32. edge &e = G[v][i];
  33. if (e.cap > && level[e.to] < ) {
  34. level[e.to] = level[v] + ;
  35. que.push(e.to);
  36. }
  37. }
  38. }
  39. }
  40.  
  41. int dfs(int v,int t,int f) {
  42. if (v == t)return f;
  43. for (int &i = iter[v]; i < G[v].size(); i++) {
  44. edge &e = G[v][i];
  45. if (e.cap > && level[v] < level[e.to]) {
  46. int d = dfs(e.to, t, min(f, e.cap));
  47. if (d > ) {
  48. e.cap -= d;
  49. G[e.to][e.rev].cap += d;
  50. return d;
  51. }
  52. }
  53. }
  54. return ;
  55. }
  56.  
  57. int max_flow(int s,int t) {
  58. int flow = ;
  59. for (; ;) {
  60. bfs(s);
  61. if (level[t] < )return flow;
  62. memset(iter, , sizeof(iter));
  63. int f;
  64. while ((f = dfs(s, t, INF)) > ) {
  65. flow += f;
  66. }
  67. }
  68. }
  69.  
  70. bool vis[MAX_N];
  71. int low[MAX_N],dfn[MAX_N],tot=;
  72. bool inStack[MAX_N];
  73.  
  74. stack<int> st;
  75. bool exitCircle=false;
  76.  
  77. void Tarjan(int u) {
  78. if (exitCircle)return;
  79. vis[u] = ;
  80. inStack[u] = ;
  81. st.push(u);
  82. low[u] = dfn[u] = ++tot;
  83. for (int i = ; i < G[u].size(); i++) {
  84. int v = G[u][i].to;
  85. if (G[u][i].cap == )continue;
  86. if (!vis[v]) {
  87. Tarjan(v);
  88. low[u] = min(low[u], low[v]);
  89. }
  90. else if (inStack[v])
  91. low[u] = min(low[u], dfn[v]);
  92. }
  93. if (dfn[u] == low[u]) {
  94. int cnt = ;
  95. while (inStack[u]) {
  96. if (st.empty())break;
  97. cnt++;
  98. //cout << st.top() << " ";
  99. inStack[st.top()] = ;
  100. st.pop();
  101. }
  102. if (cnt > )exitCircle = true;
  103. //cout << endl;
  104. }
  105. }
  106.  
  107. int T;
  108. int N,M;
  109.  
  110. int main() {
  111. cin.sync_with_stdio(false);
  112. cin >> T;
  113. int cas = ;
  114. while (T--) {
  115.  
  116. int sum = ;
  117. cin >> N >> M;
  118.  
  119. for(int i=;i<N+M+;i++)G[i].clear();
  120. memset(vis,,sizeof(vis));
  121. memset(dfn,,sizeof(dfn));
  122. memset(low,,sizeof(low));
  123. tot=;
  124. memset(inStack,,sizeof(inStack));
  125. exitCircle=false;
  126. while(st.size())st.pop();
  127.  
  128. for (int i = ; i < N; i++) {
  129. int a;
  130. cin >> a;
  131. sum += a;
  132. add_edge(, i + , a);
  133. }
  134. for (int i = ; i < M; i++) {
  135. int a;
  136. cin >> a;
  137. add_edge(N + i + , N + M + , a);
  138. }
  139. for (int i = ; i <= N; i++)
  140. for (int j = ; j <= M; j++)
  141. add_edge(i, j + N, );
  142. int flow = max_flow(, N + M + );
  143.  
  144. cout << "Case #" << ++cas << ": ";
  145. if (flow != sum) {
  146. cout << "So naive!" << endl;
  147. continue;
  148. }
  149.  
  150. for (int i = ; i <= N + M + ; i++)if (!vis[i])Tarjan(i);
  151. if (exitCircle)cout << "So young!" << endl;
  152. else cout << "So simple!" << endl;
  153. }
  154.  
  155. return ;
  156. }

hdu 4975 A simple Gaussian elimination problem 最大流+找环的更多相关文章

  1. HDU 4975 A simple Gaussian elimination problem.

    A simple Gaussian elimination problem. Time Limit: 1000ms Memory Limit: 65536KB This problem will be ...

  2. hdu 4975 A simple Gaussian elimination problem.(网络流,推断矩阵是否存在)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4975 Problem Description Dragon is studying math. One ...

  3. hdu - 4975 - A simple Gaussian elimination problem.(最大流量)

    意甲冠军:要在N好M行和列以及列的数字矩阵和,每个元件的尺寸不超过9,询问是否有这样的矩阵,是独一无二的N(1 ≤ N ≤ 500) , M(1 ≤ M ≤ 500). 主题链接:http://acm ...

  4. HDOJ 4975 A simple Gaussian elimination problem.

    和HDOJ4888是一样的问题,最大流推断多解 1.把ISAP卡的根本出不来结果,仅仅能把全为0或者全为满流的给特判掉...... 2.在残量网络中找大于2的圈要用一种类似tarjian的方法从汇点開 ...

  5. hdu4975 A simple Gaussian elimination problem.(正确解法 最大流+删边判环)(Updated 2014-10-16)

    这题标程是错的,网上很多题解也是错的. http://acm.hdu.edu.cn/showproblem.php?pid=4975 2014 Multi-University Training Co ...

  6. A simple Gaussian elimination problem.(hdu4975)网络流+最大流

    A simple Gaussian elimination problem. Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65 ...

  7. A simple Gaussian elimination problem.

    hdu4975:http://acm.hdu.edu.cn/showproblem.php?pid=4975 题意:给你一个n*m的矩阵,矩阵中的元素都是0--9,现在给你这个矩阵的每一行和每一列的和 ...

  8. hdu4975 A simple Gaussian elimination problem.(最大流+判环)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4975 题意:和hdu4888基本一样( http://www.cnblogs.com/a-clown/ ...

  9. hdu 4972 A simple dynamic programming problem(高效)

    pid=4972" target="_blank" style="">题目链接:hdu 4972 A simple dynamic progra ...

随机推荐

  1. python-DB模块实例

    MySQLdb其实有点像php或asp中连接数据库的一个模式了,只是MySQLdb是针对mysql连接了接口,我们可以在python中连接MySQLdb来实现数据的各种操作. python连接mysq ...

  2. 人脸识别源代码Open cv

    #include <stdio.h> #include <string.h> #include "cv.h" #include "cvaux.h& ...

  3. Springboot(二)-application.yml默认的配置项以及读取自定义配置

    写在前面 ===== spring-boot 版本:2.0.0.RELEASE ===== 读取自定义配置 1.配置文件:sys.properties supply.place=云南 supply.c ...

  4. 使用Hexo+Github搭建属于自己的博客

    工具:Visual Studio Code/MarkdownPad技术:Hexo+Github 创建Github项目 Github账户注册和新建项目,项目必须要遵守格式:账户名.github.io,不 ...

  5. 【支付宝支付】扫码付和app支付,回调验证签名失败问题

    在检查了参数排序,编码解码,文件编码等问题后,发现还是签名失败,最后找出原因: 扫码付和app支付采用的支付宝公钥不一样   Pid和公钥管理里面:   开放平台密钥界面和开放平台应用界面的密钥应该一 ...

  6. 面试Python工程师,这几道编码题有必要背背,Python面试题No8

    第1题:列表[1,2,3,4,5],请使用map()函数输出[1,4,9,16,25],并使用列表推导式提取出大于10的数,最终输出[16,25]. map是python高阶用法,字面意义是映射,它的 ...

  7. Python9-反射-day27(大年初三)

    复习 class 类名(父类,父类2): 静态属性 = '' #静态属性 类属性 def __init__(self): #初始化方法 self.name = 'alex' def func(self ...

  8. 00037_this关键字

    1.成员变量和局部变量同名问题 当在方法中出现了局部变量和成员变量同名的时候,可以在成员变量名前面加上this.来区别成员变量和局部变量. class Person { private int age ...

  9. python基础-面向对象(装饰器)

    属性:   @property   @method_name.setter   @method_name.deleter   三个标签都是放在方法的上面来使用,且方法名要和后续使用的   变量名字相一 ...

  10. Leetcode 365.水壶问题

    水壶问题 有两个容量分别为 x升和 y升的水壶以及无限多的水.请判断能否通过使用这两个水壶,从而可以得到恰好 z升的水? 如果可以,最后请用以上水壶中的一或两个来盛放取得的 z升 水. 你允许: 装满 ...