网络流主要解决三种问题:最大流、最小流和费用流。
最大流算法主要有三种:EK算法、Dinic算法、SAP算法。
本篇博客是关于SAP算法的。最坏的情况下,SAP算法将达到复杂度O(VE2)。
1 #include <iostream>
2 #include <cstdio>
3 #include <algorithm>
4 #include <queue>
5 #include <cstring>
6
7 using namespace std;
8 const int INF = 0x3f3f3f3f;
9 const int maxn = 200 + 10;
10 const int maxm = 200 + 10;
11
12 int n,m;
13 int head[maxn];//链式前向星
14 int tot = 0;
15
16 struct edge
17 {
18 int to;
19 int c;
20 int next;
21 edge(int x = 0, int y = 0, int z = 0) : to(x), c(y), next(z) {}
22 }es[maxm*2];//记录边 注意是2倍
23
24 void add_edge(int u, int v, int c)
25 {
26 es[tot] = edge(v,c,head[u]);
27 head[u] = tot++;
28 }
29
30
31 int SAP(int s, int t)
32 {
33 int numh[maxn],h[maxn],ce[maxn],pre[maxn];
34 //numh 记录gap优化的统计高度数量数组,h 距离标号数组,ce 当前弧,pre前驱数组
35 int f, ans = 0, u, temp, neck, i; //初始化最大流为0
36 memset(h,0,sizeof(h));
37 memset(numh,0,sizeof(numh));
38 memset(pre,-1,sizeof(pre));
39 for(i = 1; i <= n; i++) ce[i] = head[i];
40 numh[0] = n;
41 u = s;
42 while(h[s] < n)
43 {
44 //寻找增广路
45 if(u == t)
46 {
47 f = INF;
48 for(i = s; i != t; i = es[ce[i]].to)
49 {
50 if(f > es[ce[i]].c)
51 {
52 neck = i;
53 f = es[ce[i]].c;
54 }
55 }
56 for(i = s; i != t; i = es[ce[i]].to)
57 {
58 temp = ce[i];
59 es[temp].c -= f;
60 es[temp^1].c += f;
61 }
62 ans += f;
63 u = neck;
64 }
65
66 //寻找可行弧
67 for(i = ce[u]; i != -1; i = es[i].next)
68 if(es[i].c && h[u] == h[es[i].to] + 1) break;
69
70 //寻找增广路
71 if(i != -1)
72 {
73 ce[u] = i;
74 pre[es[i].to] = u;
75 u = es[i].to;
76 }
77 else
78 {
79 if(!--numh[h[u]]) break; //gap optimization
80 ce[u] = head[u];
81 for(temp = n, i = head[u]; i != -1; i = es[i].next)
82 if(es[i].c) temp = min(temp, h[es[i].to]);
83
84 h[u] = temp + 1;
85 ++numh[h[u]];
86 if(u != s) u = pre[u];//重标号并且从当前点前驱重新增广
87 }
88
89 }
90 return ans;
91 }
92
93 int main()
94 {
95 while(~scanf("%d%d",&n,&m))
96 {
97 tot = 0;
98 memset(head,-1,sizeof(head));
99 int u,v,c;
100 for(int i = 0; i < m; i++)
101 {
102 scanf("%d%d%d",&u,&v,&c);
103 add_edge(u,v,c);
104 add_edge(v,u,0);//增加反向边
105 }
106 int ans = SAP(1,n);
107 printf("%d\n",ans);
108 }
109 return 0;
110 }