Flow Problem

Myth丶恋晨 2022-01-05 15:27 422阅读 0赞

Problem Description

Network flow is a well-known difficult problem for ACMers. Given a graph, your task is to find out the maximum flow for the weighted directed graph.

Input

The first line of input contains an integer T, denoting the number of test cases. For each test case, the first line contains two integers N and M, denoting the number of vertexes and edges in the graph. (2 <= N <= 15, 0 <= M <= 1000) Next M lines, each line contains three integers X, Y and C, there is an edge from X to Y and the capacity of it is C. (1 <= X, Y <= N, 1 <= C <= 1000)

Output

For each test cases, you should output the maximum flow from source 1 to sink N.

Sample Input

2

3 2

1 2 1

2 3 1

3 3

1 2 1

2 3 1

1 3 1

Sample Output

Case 1: 1

Case 2: 2

*********************************************************************************************

网络流 纯的sap算法。(用递归)

*********************************************************************************************

ContractedBlock.gif ExpandedBlockStart.gif

  1. 1 #include<iostream>
  2. 2 #include<string>
  3. 3 #include<cstring>
  4. 4 #include<cmath>
  5. 5 #include<algorithm>
  6. 6 #include<cstdio>
  7. 7 #include<queue>
  8. 8 #include<vector>
  9. 9 #include<stack>
  10. 10 #define inf 0x3fffffff
  11. 11 using namespace std;
  12. 12 int lvl[2020],gap[2020],idx,source,sink,n,m,head[2020];
  13. 13 int T;
  14. 14 int min(int a,int b)
  15. 15 {
  16. 16 return a>b?b:a;
  17. 17 }
  18. 18 struct nodedge
  19. 19 {
  20. 20 int next;
  21. 21 int to;
  22. 22 int cap;
  23. 23 }e[2020];
  24. 24 int i,j,k,num;
  25. 25 void add(int a,int b,int c)//加边,正向&&反向
  26. 26 {
  27. 27 e[num].cap=c;
  28. 28 e[num].to=b;
  29. 29 e[num].next=head[a];
  30. 30 head[a]=num;
  31. 31 num++;
  32. 32 e[num].cap=0;
  33. 33 e[num].to=a;
  34. 34 e[num].next=head[b];
  35. 35 head[b]=num;
  36. 36 num++;
  37. 37 }
  38. 38 int dfs(int src,int aug)
  39. 39 {
  40. 40 if(src==sink)//到汇点返回
  41. 41 return aug;
  42. 42 int tf=0,sf,mlvl=n-1;
  43. 43 for(int it=head[src];it!=-1;it=e[it].next)//链式前向星
  44. 44 {
  45. 45 if(e[it].cap>0)//边仍然有容量
  46. 46 {
  47. 47 if(lvl[src]==lvl[e[it].to]+1)//判断是否为最短边
  48. 48 {
  49. 49 sf=dfs(e[it].to,min(aug-tf,e[it].cap));//向下递归,到汇点时的值
  50. 50 e[it].cap-=sf;
  51. 51 e[it^1].cap+=sf;//反向加
  52. 52 tf+=sf;//与流入节点的最大流量比较
  53. 53
  54. 54 if(lvl[source]>=n)//如果节点的层数大于最大返回(注意是反向的)
  55. 55 return tf;
  56. 56 if(tf==aug)//等于最大流量时返回
  57. 57 break;
  58. 58 }
  59. 59 mlvl=min(mlvl,lvl[e[it].to]);//求最近边
  60. 60 }
  61. 61 }
  62. 62 if(tf==0)//出现断层时
  63. 63 {
  64. 64 --gap[lvl[src]];
  65. 65 if(gap[lvl[src]]==0)
  66. 66 lvl[source]=n;
  67. 67 else
  68. 68 {
  69. 69 lvl[src]=mlvl+1;
  70. 70 gap[lvl[src]]++;
  71. 71 }
  72. 72
  73. 73 }
  74. 74 return tf;
  75. 75 }
  76. 76 int sap()
  77. 77 {
  78. 78 int ans=0;
  79. 79 gap[0]=n;
  80. 80 while(lvl[source]<n)
  81. 81 ans+=dfs(source,inf);
  82. 82 return ans;
  83. 83 }
  84. 84 int main()
  85. 85 {
  86. 86 cin>>T;
  87. 87 int st,en,c,ps=0;
  88. 88 while(T--)
  89. 89 {
  90. 90 ps++;
  91. 91 memset(lvl,0,sizeof(lvl));
  92. 92 memset(gap,0,sizeof(gap));
  93. 93 memset(head,-1,sizeof(head));
  94. 94 cin>>n>>m;
  95. 95 num=0;
  96. 96 for(i=1;i<=m;i++)
  97. 97 {
  98. 98 cin>>st>>en>>c;
  99. 99 add(st,en,c);
  100. 100 }
  101. 101 sink=n;source=1;
  102. 102 cout<<"Case "<<ps<<": "<<sap()<<endl;
  103. 103 }
  104. 104 }

奋进

转载于:https://www.cnblogs.com/sdau--codeants/p/3276303.html

发表评论

表情:
评论列表 (有 0 条评论,422人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Git Flow

    一、引入背景         在使用Git的过程中如果没有清晰流程和规划,否则,每个人都提交一堆杂乱无章的commit,项目很快就会变得难以协调和维护。Git版本管理同样需要

    相关 认识 Flow

    [Flow][] 是 facebook 出品的 JavaScript 静态类型检查工具。Vue.js 的源码利用了 Flow 做了静态类型检查,所以了解 Flow 有助于我们阅