原题链接

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. POI读word docx 07 文件的两种方法

    POI在读写word docx文件时是通过xwpf模块来进行的,其核心是XWPFDocument.一个XWPFDocument代表一个docx文档,其可以用来读docx文档,也可以用来写docx文档. ...

  2. ios之NSNumber

    NSNumber + (NSNumber *)numberWithInt:(int)value; + (NSNumber *)numberWithDouble:(double)value; - (in ...

  3. [LUOGU] P1908 逆序对

    题目描述 猫猫TOM和小老鼠JERRY最近又较量上了,但是毕竟都是成年人,他们已经不喜欢再玩那种你追我赶的游戏,现在他们喜欢玩统计.最近,TOM老猫查阅到一个人类称之为"逆序对"的 ...

  4. 如何用纯 CSS 创作一个永动的牛顿摆

    效果预览 在线演示 按下右侧的"点击预览"按钮可以在当前页面预览,点击链接可以全屏预览. https://codepen.io/comehope/pen/qKmGaJ 可交互视频教 ...

  5. Python-求解两个字符串的最长公共子序列

    一.问题描述 给定两个字符串,求解这两个字符串的最长公共子序列(Longest Common Sequence).比如字符串1:BDCABA:字符串2:ABCBDAB.则这两个字符串的最长公共子序列长 ...

  6. 剑指Offer(书):对称的二叉树

    题目:请实现一个函数,用来判断一颗二叉树是不是对称的.注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的. boolean isSymmetrical(TreeNode pRoot) { r ...

  7. CentOS 7.0:搭建SVN服务器

    1. 通过 yum install subversion来安装 2. 提示已经安装.查看svn版本 第二步: 创建svn版本库 第三步: 配置svn信息 2. 配置权限配置文件authz 3. 配置用 ...

  8. jdbc 和 hibernate 比较

    相同点:都是数据库操作的中间件,都不是线程安全需要即时关闭,都可以对数据库操作进行显式处理. 不同:jdbc使用标准sql语言,hibernate使用HQL,操作对象jdbc直接操作数据传送到数据库, ...

  9. Leetcode 365.水壶问题

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

  10. [android开发篇]elicpse安装教程

    http://www.runoob.com/eclipse/eclipse-install.html Eclipse 安装(Neon 版本) Eclipse 最新版本 Eclipse Neon,这个首 ...