网络流-最大流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 }
View Code

猜你喜欢

转载自www.cnblogs.com/Juruo1103/p/10500163.html