网络流-最大流ISAP
之前学了ek和dinic,虽然dinic可以解决一般的最大流问题,但是有时候会被卡,所以我们考虑使用更快的ISAP算法
改变
ISAP和dinic一样使用分层标号来规定Dfs的进行方向。但是ISAP进行的是从终点反向标号,这样每次增广到一个点直接提升它的标号即可,把多次Bfs变成了一次Bfs,节省时间
优化
断层优化。当增广过程中全图出现了断层,即一个高度上没有任何节点,那么可以直接停止程序进行
代码实现
1 #include <cstdio>
2 #include <queue>
3 #include <cstring>
4 #include <algorithm>
5
6 using std::queue;
7 using std::min;
8 using std::max;
9
10 const int MAXN = 1e4 + 5;
11 const int INF = 0x3f3f3f3f;
12
13 int n, m, s, t;
14
15 struct Edge{
16 int to, val;
17 Edge *next, *opps;
18 Edge(int to, int val, Edge *next):to(to), val(val), next(next){opps = NULL;}
19 };
20
21 Edge *head[MAXN];
22
23 void AddEdge(int u, int v, int w) {
24 head[u] = new Edge(v, w, head[u]);
25 head[v] = new Edge(u, 0, head[v]);
26 head[u]->opps = head[v]; head[v]->opps = head[u];
27 }
28
29 namespace ISAP{
30 int gap[MAXN], dep[MAXN], maxflow = 0;
31 Edge *cur[MAXN];
32
33 void Bfs(int t) {
34 memset(dep, -1, sizeof(dep));
35 memset(gap, 0, sizeof(gap));
36 queue <int> q;
37 dep[t] = 0; gap[0] = 1;
38 q.push(t);
39 while (!q.empty()) {
40 int u = q.front(); q.pop();
41 for (Edge *e = head[u]; e; e = e->next) {
42 int v = e->to;
43 if (dep[v] != -1) continue;
44 q.push(v);
45 dep[v] = dep[u] + 1;
46 gap[dep[v]]++;
47 }
48 }
49 }
50
51 int Dfs(int u, int flow) {
52 if (u == t) {
53 maxflow += flow;
54 return flow;
55 }
56 int used = 0;
57 for (Edge *&e = cur[u]; e; e = e->next) {
58 int v = e->to;
59 if (e->val && dep[v] == dep[u] - 1) {
60 int mi = Dfs(v, min(e->val, flow - used));
61 if (mi) {
62 used += mi;
63 e->val -= mi;
64 e->opps->val += mi;
65 }
66 if (used == flow) return used;
67 }
68 }
69 --gap[dep[u]];
70 if (gap[dep[u]] == 0) dep[s] = n + 1;
71 cur[u] = head[u];
72 dep[u]++;
73 ++gap[dep[u]];
74 return used;
75 }
76
77 void Work(int s, int t) {
78 maxflow = 0;
79 memcpy(cur, head, sizeof(head));
80 Bfs(t);
81 while (dep[s] < n) Dfs(s, INF);
82 }
83 }
84
85 void Pre() {
86 scanf("%d %d %d %d", &n, &m, &s, &t);
87 memset(head, 0, sizeof(head));
88 int x, y, z;
89 for (int i = 1; i <= m; i++) {
90 scanf("%d %d %d", &x, &y, &z);
91 AddEdge(x, y, z);
92 }
93 }
94
95 int main() {
96 Pre();
97 ISAP::Work(s, t);
98 printf("%d\n", ISAP::maxflow);
99 return 0;
100 }