序:
在之前的博文中,我解释了关于最大流的EK与Dinic算法,以及它们的STL/非STL的实现(其实没什么区别)。本次讲解的是ISAP算法。‘I’,指 improved,也就是说ISAP其实是SAP算法的改进。目前没有官方名称。

经过测试,ISAP的效率洛谷的板子题远胜于EK和Dinic的,速度大概是它们的2-3倍。代码量实际上并没有多大变化,在20行读入优化与不压行的情况下(即下文代码),200-210行。(如果压行的话,120行问题不大。不要问我为什么,我空行太多…如果加读入优化的话,再加上15行)

本文给出三种实现方式:递归,非递归,STL,非STL,将ISAP用结构体封装,直接调用函数(每种包含几个,实际上并没有什么差别)。

温馨提示:
在开启O2优化后,vector+queue版的ISAP比数组模拟的要快一点点(10ms?,运行时间均在90-110ms之间)。
如果不开优化数组模拟比STL版要快2-3倍,达到120-150ms,而STL版是350-400ms(多次提交测试)。
什么级别的考试用什么,这应该很好取舍


ISAP的思路:
当我们使用Dinic跑最大流的时候,我们多次进行了BFS分层,直到汇点不在残余网络之中。而ISAP只BFS分层一次(事实上你都甚至可以不进行分层,也就比分层慢一点)。ISAP通过新的方式分层。

对于任意一个节点x,当跑完数次最大流之后,我们发现所有与它相连的节点都不满足level[i]+1 == level[x]了。出现这种情况,Dinic的做法是重新分层,而ISAP的做法是将level[x]置成min(level[i])+1从而构造出一条可行流

当然,这是有边界的。我们从汇点开始分层,源点的层数最高是n-1(一条链),所以当level[st] >= n的时候,算法结束,残余网络中一定不存在可行流了。
这种方式也就解释了为什么可以不预先分层。因为这样,分层的工作就留给了每一次推进可行流之中(否则无法找到可行流)。

注:分层时从汇点分层

但是如果仅仅是这样,实际上快不了多少。


真正的优化在于这两个:gap优化和当前弧(cur)优化

gap优化:
Dinic的反复分层被改成了ISAP的向上构造,而可行流必须满足level[起点] = level[终点]+1,也就是说如果出现了断层,也就是说在某一level的层级中不存在节点,那么就不会再出现可行流(比如这一层是x,那么流无法从lev.(x-1)流到lev.(x+1)),直接结束算法,比不加它的ISAP快到不知哪里去了

cur优化(当前弧):
对于任意一个节点x,假设最大流已经经过它流向下一个节点,而后在某次又流到了它(比如说已经找到一条可行流,从源点重新寻找可行流,再次到达该节点),那么该可行流一定不能再流到之前流过的那些弧了(那些弧已经流过了,再进去相当于又走了一遍老路,但是上一次已经最大化的利用了它的流量限制,也就是说这次是没有任何意义的行为。)
为了避免这种情况,我们用一个数组cur[]来记录每个节点当前流到的弧的编号(这是边表存储的情况。如果是邻接矩阵存储,那就记录当前流到了下一个节点的编号),当下一次又经过该节点的时候,我们只需要再去尝试没有流过的弧了。

举个例子:
节点5有三条弧,分别是arc1,arc2,arc3 。在之前寻找可行流的过程中,经过了arc1。那么将cur[5] = arc2,下一次便从arc2开始寻找可行流。

可能会有这样一个问题
凭什么就说arc1就没有再走的价值了,那如果上一次通过arc1流向了节点6,而可行流最终是通过节点6的某一条弧流向汇点的,但是节点6不一定只有一条弧啊,下一次还可以走节点6的其他弧

解释也很简单,这是递归的过程,如果流已经流回到了节点5,那么说明节点6以及arc1所抵达的所有节点都已经进行了这项操作

当然,如果出现对某结点重新分层的时候,要将该节点的cur置回0(因为当前已经到尾了)。


代码实现:
1.STL+DFS+非结构体版:

  1. /*
  2. About: Max_flow ISAP STL+DFS
  3. Auther: kongse_qi
  4. Date: 2017/04/30
  5. */
  6. #include <iostream>
  7. #include <cstdio>
  8. #include <algorithm>
  9. #include <vector>
  10. #include <cstdlib>
  11. #include <cstring>
  12. #include <ctype.h>
  13. #include <queue>
  14. #define maxn 10005
  15. #define maxm 200005
  16. #define INF 0x3f3f3f
  17. #define read(x) Get_Int(), x = in
  18. #define p_b(x) push_back(x)
  19. using namespace std;
  20. struct Edge{
  21. int st, en, weight;
  22. Edge(){}
  23. Edge(int s, int e, int w):
  24. st(s), en(e), weight(w){}
  25. }edge[maxm];
  26. vector<int> arc[maxn];
  27. typedef vector<int>::iterator iterator_t;
  28. int n, m, st, en, tot;
  29. int max_flow;
  30. int num[maxn];
  31. int dis[maxn];
  32. int cur[maxn];
  33. int pre[maxn];
  34. char *X, *Buffer, c;
  35. int in;
  36. void Get_All()
  37. {
  38. fseek(stdin, 0, SEEK_END);
  39. int file_lenth = ftell(stdin);
  40. rewind(stdin);
  41. Buffer = (char*)malloc(file_lenth*sizeof(char));
  42. fread(Buffer, 1, file_lenth, stdin);
  43. X = Buffer;
  44. c = *X;
  45. return ;
  46. }
  47. void Get_Int()
  48. {
  49. in = 0;
  50. while(!isdigit(c)) c = *++X;
  51. while(isdigit(c))
  52. {
  53. in = in*10+c-'0';
  54. c = *++X;
  55. }
  56. return ;
  57. }
  58. void Init()
  59. {
  60. //freopen("test.in", "r", stdin);
  61. Get_All();
  62. tot = -1;
  63. read(n), read(m);
  64. read(st), read(en);
  65. int a, b, c;
  66. for(int i = 0; i != m; ++i)
  67. {
  68. read(a), read(b), read(c);
  69. edge[++tot] = Edge(a, b, c);
  70. edge[++tot] = Edge(b, a, 0);
  71. arc[a].p_b(tot-1);
  72. arc[b].p_b(tot);
  73. }
  74. return ;
  75. }
  76. bool Bfs()
  77. {
  78. bool wh[maxn];
  79. memset(wh, 0, sizeof wh);
  80. queue<int> q;
  81. q.push(en);
  82. wh[en] = true;
  83. while(!q.empty())
  84. {
  85. int cur = q.front(); q.pop();
  86. for(iterator_t i = arc[cur].begin(); i != arc[cur].end(); ++i)
  87. {
  88. Edge& ne = edge[*i];
  89. if(wh[ne.en] == false)
  90. {
  91. dis[ne.en] = dis[cur]+1;
  92. q.push(ne.en);
  93. wh[ne.en] = true;
  94. }
  95. }
  96. }
  97. if(wh[st] == false) return false;
  98. return true;
  99. }
  100. int Augment(int x)
  101. {
  102. int minn = INF;
  103. while(x != st)
  104. {
  105. Edge& e = edge[pre[x]];
  106. minn = min(minn, e.weight);
  107. x = e.st;
  108. }
  109. x = en;
  110. while(x != st)
  111. {
  112. int curr = pre[x];
  113. edge[curr].weight -= minn;
  114. edge[curr^1].weight += minn;
  115. x = edge[curr].st;
  116. }
  117. return minn;
  118. }
  119. void Advance(int x)
  120. {
  121. bool wh = false;
  122. for(int& i = cur[x]; i != arc[x].size(); ++i)
  123. {
  124. Edge& e = edge[arc[x][i]];
  125. if(e.weight > 0 && dis[x] == dis[e.en]+1)
  126. {
  127. wh = true;
  128. pre[e.en] = arc[x][i];
  129. x = e.en;
  130. break;
  131. }
  132. }
  133. if(wh == false)
  134. {
  135. int m = n-1;
  136. for(iterator_t i = arc[x].begin(); i != arc[x].end(); ++i)
  137. {
  138. Edge& e = edge[*i];
  139. if(e.weight > 0)
  140. {
  141. m = min(m, dis[e.en]);
  142. }
  143. }
  144. if(--num[dis[x]] == 0) return ;
  145. ++num[dis[x] = m+1];
  146. cur[x] = 0;
  147. if(x != st) x = edge[pre[x]].st;
  148. }
  149. if(x == en)
  150. {
  151. max_flow += Augment(en);
  152. x = st;
  153. }
  154. if(dis[st] >= n) return ;
  155. Advance(x);
  156. return ;
  157. }
  158. int Isap()
  159. {
  160. if(Bfs())
  161. {
  162. for(int i = 1; i != n+1; ++i)
  163. {
  164. ++num[dis[i]];
  165. }
  166. Advance(st);
  167. }
  168. else return -1;
  169. return max_flow;
  170. }
  171. int main()
  172. {
  173. Init();
  174. printf("%d\n", Isap());
  175. return 0;
  176. }

2.struct+非STL+BFS版 (不开O2它最快)

  1. /*
  2. About: Max_flow ISAP struct 非STL+BFS
  3. Auther: kongse_qi
  4. Date: 2017/04/30
  5. */
  6. #include <iostream>
  7. #include <cstdio>
  8. #include <algorithm>
  9. #include <cstdlib>
  10. #include <cstring>
  11. #include <ctype.h>
  12. #define maxn 10005
  13. #define maxm 200005
  14. #define INF 0x3f3f3f
  15. #define read(x) Get_Int(), x = in
  16. using namespace std;
  17. void Get_Int();
  18. void Get_All();
  19. char *X, *Buffer, c;
  20. int in;
  21. struct Edge{
  22. int st, en, weight;
  23. Edge(){}
  24. Edge(int s, int e, int w):
  25. st(s), en(e), weight(w){}
  26. };
  27. struct Isap{
  28. int st, en, tot, n, m;
  29. int max_flow;
  30. int num[maxn];
  31. int dis[maxn];
  32. int cur[maxn];
  33. int pre[maxn];
  34. int arc[maxn][maxn/50];
  35. int amount[maxn];
  36. Edge edge[maxm];
  37. void Init(int st, int en, int n, int m)
  38. {
  39. tot = -1;
  40. this -> st = st; this -> en = en;
  41. this -> n = n; this -> m = m;
  42. max_flow = 0;
  43. memset(cur, 0, sizeof cur);
  44. memset(num, 0, sizeof num);
  45. memset(amount, -1, sizeof amount);
  46. return ;
  47. }
  48. void Add_edge(int s, int e, int w)
  49. {
  50. edge[++tot] = Edge(s, e, w);
  51. edge[++tot] = Edge(e, s, 0);
  52. arc[s][++amount[s]] = tot-1;
  53. arc[e][++amount[e]] = tot;
  54. return ;
  55. }
  56. bool Bfs()
  57. {
  58. bool wh[maxn];
  59. memset(wh, 0, sizeof wh);
  60. int q[maxn], st_pos = -1, en_pos = -1;
  61. q[++en_pos] = en;
  62. wh[en] = true;
  63. while(st_pos != en_pos)
  64. {
  65. int cur = q[++st_pos];
  66. for(int i = 0; i != amount[cur]+1; ++i)
  67. {
  68. Edge& ne = edge[arc[cur][i]];
  69. if(wh[ne.en] == false)
  70. {
  71. dis[ne.en] = dis[cur]+1;
  72. q[++en_pos] = ne.en;
  73. wh[ne.en] = true;
  74. }
  75. }
  76. }
  77. if(wh[st] == false) return false;
  78. return true;
  79. }
  80. int Augment(int x)
  81. {
  82. int minn = INF;
  83. while(x != st)
  84. {
  85. Edge& e = edge[pre[x]];
  86. minn = min(minn, e.weight);
  87. x = e.st;
  88. }
  89. x = en;
  90. while(x != st)
  91. {
  92. int curr = pre[x];
  93. edge[curr].weight -= minn;
  94. edge[curr^1].weight += minn;
  95. x = edge[curr].st;
  96. }
  97. return minn;
  98. }
  99. void Advance(int x)
  100. {
  101. while(dis[st] < n)
  102. {
  103. bool wh = false;
  104. for(int& i = cur[x]; i != amount[x]+1; ++i)
  105. {
  106. Edge& e = edge[arc[x][i]];
  107. if(e.weight > 0 && dis[x] == dis[e.en]+1)
  108. {
  109. wh = true;
  110. pre[e.en] = arc[x][i];
  111. x = e.en;
  112. break;
  113. }
  114. }
  115. if(wh == false)
  116. {
  117. int m = n-1;
  118. for(int i = 0; i != amount[x]+1; ++i)
  119. {
  120. Edge& e = edge[arc[x][i]];
  121. if(e.weight > 0)
  122. {
  123. m = min(m, dis[e.en]);
  124. }
  125. }
  126. if(--num[dis[x]] == 0) return ;
  127. ++num[dis[x] = m+1];
  128. cur[x] = 0;
  129. if(x != st) x = edge[pre[x]].st;
  130. }
  131. if(x == en)
  132. {
  133. max_flow += Augment(en);
  134. x = st;
  135. }
  136. }
  137. return ;
  138. }
  139. int Max_flow()
  140. {
  141. Bfs();
  142. for(int i = 1; i != n+1; ++i)
  143. {
  144. ++num[dis[i]];
  145. }
  146. Advance(st);
  147. return max_flow;
  148. }
  149. }doit;
  150. int main()
  151. {
  152. int a, b, c, n, m, st, en;
  153. freopen("test.in", "r", stdin);
  154. Get_All();
  155. read(n), read(m);
  156. read(st), read(en);
  157. doit.Init(st, en, n, m);
  158. for(int i = 0; i != m; ++i)
  159. {
  160. read(a), read(b), read(c);
  161. doit.Add_edge(a, b, c);
  162. }
  163. printf("%d\n", doit.Max_flow());
  164. return 0;
  165. }
  166. void Get_All()
  167. {
  168. fseek(stdin, 0, SEEK_END);
  169. int file_lenth = ftell(stdin);
  170. rewind(stdin);
  171. Buffer = (char*)malloc(file_lenth*sizeof(char));
  172. fread(Buffer, 1, file_lenth, stdin);
  173. X = Buffer;
  174. c = *X;
  175. return ;
  176. }
  177. void Get_Int()
  178. {
  179. in = 0;
  180. while(!isdigit(c)) c = *++X;
  181. while(isdigit(c))
  182. {
  183. in = in*10+c-'0';
  184. c = *++X;
  185. }
  186. return ;
  187. }

3 struct+STL+BFS版

  1. /*
  2. About: Max_flow ISAP struct STL+BFS
  3. Auther: kongse_qi
  4. Date: 2017/04/30
  5. */
  6. #pragma GCC optimize(3)
  7. #include <iostream>
  8. #include <cstdio>
  9. #include <algorithm>
  10. #include <vector>
  11. #include <cstdlib>
  12. #include <cstring>
  13. #include <ctype.h>
  14. #include <queue>
  15. #define maxn 10005
  16. #define maxm 200005
  17. #define INF 0x3f3f3f
  18. #define read(x) Get_Int(), x = in
  19. #define p_b(x) push_back(x)
  20. using namespace std;
  21. void Get_Int();
  22. void Get_All();
  23. char *X, *Buffer, c;
  24. int in;
  25. typedef vector<int>::iterator iterator_t;
  26. struct Edge{
  27. int st, en, weight;
  28. Edge(){}
  29. Edge(int s, int e, int w):
  30. st(s), en(e), weight(w){}
  31. };
  32. struct Isap{
  33. int st, en, tot, n, m;
  34. int max_flow;
  35. int num[maxn];
  36. int dis[maxn];
  37. int cur[maxn];
  38. int pre[maxn];
  39. vector<int> arc[maxn];
  40. Edge edge[maxm];
  41. void Init(int st, int en, int n, int m)
  42. {
  43. tot = -1;
  44. this -> st = st; this -> en = en;
  45. this -> n = n; this -> m = m;
  46. for(int i = 1; i != n+1; ++i)
  47. {
  48. arc[i].clear();
  49. }
  50. max_flow = 0;
  51. memset(cur, 0, sizeof cur);
  52. memset(num, 0, sizeof num);
  53. return ;
  54. }
  55. void Add_edge(int s, int e, int w)
  56. {
  57. edge[++tot] = Edge(s, e, w);
  58. edge[++tot] = Edge(e, s, 0);
  59. arc[s].p_b(tot-1);
  60. arc[e].p_b(tot);
  61. return ;
  62. }
  63. bool Bfs()
  64. {
  65. bool wh[maxn];
  66. memset(wh, 0, sizeof wh);
  67. queue<int> q;
  68. q.push(en);
  69. wh[en] = true;
  70. while(!q.empty())
  71. {
  72. int cur = q.front(); q.pop();
  73. for(iterator_t i = arc[cur].begin(); i != arc[cur].end(); ++i)
  74. {
  75. Edge& ne = edge[*i];
  76. if(wh[ne.en] == false)
  77. {
  78. dis[ne.en] = dis[cur]+1;
  79. q.push(ne.en);
  80. wh[ne.en] = true;
  81. }
  82. }
  83. }
  84. if(wh[st] == false) return false;
  85. return true;
  86. }
  87. int Augment(int x)
  88. {
  89. int minn = INF;
  90. while(x != st)
  91. {
  92. Edge& e = edge[pre[x]];
  93. minn = min(minn, e.weight);
  94. x = e.st;
  95. }
  96. x = en;
  97. while(x != st)
  98. {
  99. int curr = pre[x];
  100. edge[curr].weight -= minn;
  101. edge[curr^1].weight += minn;
  102. x = edge[curr].st;
  103. }
  104. return minn;
  105. }
  106. void Advance(int x)
  107. {
  108. while(dis[st] < n)
  109. {
  110. bool wh = false;
  111. for(int& i = cur[x]; i != arc[x].size(); ++i)
  112. {
  113. Edge& e = edge[arc[x][i]];
  114. if(e.weight > 0 && dis[x] == dis[e.en]+1)
  115. {
  116. wh = true;
  117. pre[e.en] = arc[x][i];
  118. x = e.en;
  119. break;
  120. }
  121. }
  122. if(wh == false)
  123. {
  124. int m = n-1;
  125. for(iterator_t i = arc[x].begin(); i != arc[x].end(); ++i)
  126. {
  127. Edge& e = edge[*i];
  128. if(e.weight > 0)
  129. {
  130. m = min(m, dis[e.en]);
  131. }
  132. }
  133. if(--num[dis[x]] == 0) return ;
  134. ++num[dis[x] = m+1];
  135. cur[x] = 0;
  136. if(x != st) x = edge[pre[x]].st;
  137. }
  138. if(x == en)
  139. {
  140. max_flow += Augment(en);
  141. x = st;
  142. }
  143. }
  144. return ;
  145. }
  146. int Max_flow()
  147. {
  148. Bfs();
  149. for(int i = 1; i != n+1; ++i)
  150. {
  151. ++num[dis[i]];
  152. }
  153. Advance(st);
  154. return max_flow;
  155. }
  156. }doit;
  157. int main()
  158. {
  159. int a, b, c, n, m, st, en;
  160. //freopen("test.in", "r", stdin);
  161. Get_All();
  162. read(n), read(m);
  163. read(st), read(en);
  164. doit.Init(st, en, n, m);
  165. for(int i = 0; i != m; ++i)
  166. {
  167. read(a), read(b), read(c);
  168. doit.Add_edge(a, b, c);
  169. }
  170. printf("%d\n", doit.Max_flow());
  171. return 0;
  172. }
  173. void Get_All()
  174. {
  175. fseek(stdin, 0, SEEK_END);
  176. int file_lenth = ftell(stdin);
  177. rewind(stdin);
  178. Buffer = (char*)malloc(file_lenth*sizeof(char));
  179. fread(Buffer, 1, file_lenth, stdin);
  180. X = Buffer;
  181. c = *X;
  182. return ;
  183. }
  184. void Get_Int()
  185. {
  186. in = 0;
  187. while(!isdigit(c)) c = *++X;
  188. while(isdigit(c))
  189. {
  190. in = in*10+c-'0';
  191. c = *++X;
  192. }
  193. return ;
  194. }

结构体版实际上就是将函数作为结构体的成员函数运行,在主函数中调用时逻辑会更加清晰(分区很明显)。


实测结果:

O2优化情况下:
1.耗时:115ms
内存:17281kb

2.耗时:80ms
内存:23304kb

3.耗时:103ms
内存:17281kb

其实差距不大

不开O2的情况下:

1.耗时:322ms
内存:17429kb

2.耗时:141ms
内存:23304kb

3.耗时:323ms
内存:17292kb
(结果不一定十分稳定)
因此不开优化的STL非常不建议使用的。
STL的快速与便捷只有在开启优化的情况下才能兼得。


压行代码

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <algorithm>
  4. #include <cstdlib>
  5. #include <cstring>
  6. #include <ctype.h>
  7. #include <vector>
  8. #define maxn 10005
  9. #define maxm 200005
  10. #define INF 0x3f3f3f
  11. using namespace std;
  12. struct Edge{
  13. int st, en, weight;
  14. Edge(){}
  15. Edge(int s, int e, int w):
  16. st(s), en(e), weight(w){}
  17. };
  18. struct Isap{
  19. int st, en, tot, n, m, max_flow;
  20. int num[maxn], dis[maxn], cur[maxn], pre[maxn], arc[maxn][100], amount[maxn];
  21. vector<Edge> edge;
  22. void Init(int st, int en, int n, int m){
  23. tot = -1;
  24. this -> st = st; this -> en = en;
  25. this -> n = n; this -> m = m;
  26. max_flow = 0;
  27. edge.resize(m*2);
  28. memset(cur, 0, sizeof cur);
  29. memset(num, 0, sizeof num);
  30. memset(amount, -1, sizeof amount);
  31. }
  32. void Add_edge(int s, int e, int w){
  33. edge[++tot] = Edge(s, e, w);
  34. edge[++tot] = Edge(e, s, 0);
  35. arc[s][++amount[s]] = tot-1;
  36. arc[e][++amount[e]] = tot;
  37. }
  38. void Bfs(){
  39. bool wh[maxn] = {0};
  40. int q[maxn], st_pos = -1, en_pos = -1;
  41. q[++en_pos] = en;
  42. wh[en] = true;
  43. while(st_pos != en_pos){
  44. int cur = q[++st_pos];
  45. for(int i = 0; i != amount[cur]+1; ++i){
  46. Edge ne = edge[arc[cur][i]];
  47. if(wh[ne.en] == false){
  48. dis[ne.en] = dis[cur]+1;
  49. q[++en_pos] = ne.en;
  50. wh[ne.en] = true;
  51. }
  52. }
  53. }
  54. }
  55. int Augment(){
  56. int minn = INF, curr;
  57. Edge e;
  58. for(int x = en; x != st; ){
  59. e = edge[pre[x]];
  60. minn = min(minn, e.weight);
  61. x = e.st;
  62. }
  63. for(int x = en; x != st;){
  64. curr = pre[x];
  65. edge[curr].weight -= minn;
  66. edge[curr^1].weight += minn;
  67. x = edge[curr].st;
  68. }
  69. return minn;
  70. }
  71. void Advance(int x){
  72. while(dis[st] < n){
  73. bool wh = false;
  74. for(int& i = cur[x]; i != amount[x]+1; ++i){
  75. Edge &e = edge[arc[x][i]];
  76. if(e.weight > 0 && dis[x] == dis[e.en]+1){
  77. wh = true;
  78. pre[e.en] = arc[x][i];
  79. x = e.en;
  80. break;
  81. }
  82. }
  83. if(wh == false){
  84. int minn = n-1;
  85. for(int i = 0; i != amount[x]+1; ++i){
  86. Edge& e = edge[arc[x][i]];
  87. if(e.weight > 0)
  88. minn = min(minn, dis[e.en]);
  89. }
  90. if(--num[dis[x]] == 0) return ;
  91. ++num[dis[x] = minn+1];
  92. cur[x] = 0;
  93. if(x != st) x = edge[pre[x]].st;
  94. }
  95. if(x == en) {
  96. max_flow += Augment();
  97. x = st;
  98. }
  99. }
  100. }
  101. int Max_flow(){
  102. Bfs();
  103. for(int i = 1; i != n+1; ++i)
  104. ++num[dis[i]];
  105. Advance(st);
  106. return max_flow;
  107. }
  108. }doit;
  109. int main(){
  110. int a, b, c, n, m, st, en;
  111. //freopen("test.in", "r", stdin);
  112. scanf("%d%d", &n, &m);
  113. st = 1, en = n;
  114. doit.Init(st, en, n, m);
  115. for(int i = 0; i != m; ++i){
  116. scanf("%d%d%d", &a, &b, &c);
  117. doit.Add_edge(a, b, c);
  118. }
  119. printf("%d\n", doit.Max_flow());
  120. return 0;
  121. }

(121行total)


自此结束。
箜瑟_qi 2017.04.30 23:20
四月最后一篇。

最大流算法之ISAP的更多相关文章

  1. 最大流算法-ISAP

    引入 最大流算法分为两类,一种是增广路算法,一种是预留推进算法.增广路算法包括时间复杂度\(O(nm^2)\)的EK算法,上界为\(O(n^2m)\)的Dinic算法,以及一些其他的算法.EK算法直接 ...

  2. HDOJ-3416(最大流+最短路+ISAP算法+向前星dijikstra算法+如何判断一条边是否在最短路中)

    Marriage Match IV HDOJ-3416 这题的题意就是要找两点之间最短路的路径个数,而且边不能重复. 最大流和最短路的结合.首先正向和反向建图,再跑两遍dijikstra.到这里就求出 ...

  3. Ford-Fulkerson 最大流算法

    流网络(Flow Networks)指的是一个有向图 G = (V, E),其中每条边 (u, v) ∈ E 均有一非负容量 c(u, v) ≥ 0.如果 (u, v) ∉ E 则可以规定 c(u, ...

  4. 算法9-5:最大流算法的Java代码

    残留网络 在介绍最大流算法之前先介绍一下什么是残留网络.残余网络的概念有点类似于集合中的补集概念. 下图是残余网络的样例. 上面的网络是原始网络.以下的网络是计算出的残留网络.残留网络的作用就是用来描 ...

  5. 海量数据挖掘MMDS week3:流算法Stream Algorithms

    http://blog.csdn.net/pipisorry/article/details/49183379 海量数据挖掘Mining Massive Datasets(MMDs) -Jure Le ...

  6. 基于.net的分布式系统限流组件(限流算法:令牌算法和漏斗算法)

    转载链接:https://www.cnblogs.com/vveiliang/p/9049393.html 1.令牌桶算法 令牌桶算法是比较常见的限流算法之一,大概描述如下: 1).所有的请求在处理之 ...

  7. 常用限流算法与Guava RateLimiter源码解析

    在分布式系统中,应对高并发访问时,缓存.限流.降级是保护系统正常运行的常用方法.当请求量突发暴涨时,如果不加以限制访问,则可能导致整个系统崩溃,服务不可用.同时有一些业务场景,比如短信验证码,或者其它 ...

  8. Cable TV Network 顶点连通度 (最大流算法)

    Cable TV Network 题目抽象:给出含有n个点顶点的无向图,给出m条边.求定点联通度   K 算法:将每个顶点v拆成 v'   v''  ,v'-->v''的容量为1.       ...

  9. 最大流算法 ISAP 模板 和 Dinic模板

    ISAP // UVa11248 Frequency Hopping:使用ISAP算法,加优化 // Rujia Liu struct Edge { int from, to, cap, flow; ...

随机推荐

  1. JavaScript当页面关闭时向后台发送请求

    今天做项目时遇上一个需求,当浏览器或页面关闭时将数据存储到数据库内.实现思想是采用js监测onunload然后发送请求.结果失败,刷新可以发送但是关闭并不能,整了一整天并没有解决,最后找到了解决办法. ...

  2. 【G】系列导航

    G.开源的分布式部署解决方案 [G]开源的分布式部署解决方案 - 预告篇 [G]开源的分布式部署解决方案(一) - 开篇 [G]开源的分布式部署解决方案(二) - 好项目是从烂项目基础上重构出来的 [ ...

  3. 设置int、float型数据的输出格式

    设置整型输出的有效位数,比如在输出时间时时.分.秒都是两位有效数字,如果是5分钟应该输出00:05:00.需要加上头文件<iomanip> cout<<setw(2)<& ...

  4. php基本数据类型需要注意的地方

    一.布尔(Boolean) 手册中提到特殊类型NULL(包括尚未赋值的变量)会被换为false值,我自己在测试的时候发现NULL值可以转换为false,虽然false也会输出,但是尚未赋值的变量会报N ...

  5. 任务调度之持久化(基于Quartz.net)

    上一篇我们了解了任务调度及他的远端管理方式,传送门:任务调度及远端管理(基于Quartz.net) 这篇我们要完成任务调度的持久化功能,即新增修改删除之类的功能,这必须得要有的,不然都不知道后台都有什 ...

  6. jQuery获取Select选择的Text和 Value(转,待测试确认)

    在自己写的第一个小项目的省市区联动的时候需要用到select,找到这篇文章.实在是觉得太好了,忍不住转过来.待日后测试后再修改整理次文章. 下面是文章原文 jQuery获取Select选择的Text和 ...

  7. 动态代理的两种实现方式(JDK/Cglib)

    =========================================== 原文链接: 动态代理的两种实现方式(JDK/Cglib) 转载请注明出处! ================== ...

  8. MySQL(Navicat)运行.sql文件时报错[Err] 2006 - MySQL server has gone away 的解决方法

    在my.ini里加上  max_allowed_packet=16M

  9. android开发用无线网络进行Android开发中的调试

    1.手机具有root权限 2.安装adbWireless1.5.4.apk (下面有下载地址) 3.敲入命令:adb connect 192.168.1.127  后面是手机的IP地址 打开eclip ...

  10. c#FTP操作类,包含上传,下载,删除,获取FTP文件列表文件夹等Hhelp类

    有些时间没发表文章了,之前用到过,这是我总结出来关于ftp相关操作一些方法,网上也有很多,但是没有那么全面,我的这些仅供参考和借鉴,希望能够帮助到大家,代码和相关引用我都复制粘贴出来了,希望大家喜欢 ...