[洛谷 P3376] 网络最大流 | 模板 (ISAP 算法) 入门

题目链接

题目描述

如题,给出一个网络图,以及其源点和汇点,求出其网络最大流。

输入格式

第一行包含四个正整数 n n n, m m m, s s s, t t t,分别表示点的个数、有向边的个数、源点序号、汇点序号。

接下来M行每行包含三个正整数 ui ,vi,wi ,表示第 i 条有向边从 ui 出发,到达 vi,边权为 wi即该边最大流量为 wi)。
输出格式

一行,包含一个正整数,即为该网络的最大流。
输入输出样例

4 5 4 3
4 2 30
4 3 20
2 3 20
2 1 30
1 3 40
50

样例输入输出 1 解释

在这里插入图片描述在这里插入图片描述

struct Edge {
    int u, v;
    ll cap, flow;
    Edge(int _u, int _v, ll _cap, ll _flow) {
        u = _u, v = _v, cap = _cap, flow = _flow;
    }
};
struct ISAP {
    vector<Edge> edge;
    vector<int> G[maxn];
    ll dis[maxn], cur[maxn];
    int n, s, t;
    ll p[maxn], num[maxn];
    bool vis[maxn];
    void init(int _n, int _s, int _t) {
        this->n = _n, this->s = _s, this->t = _t;
        for (int i = 1; i <= _n; i++) G[i].clear();
        edge.clear();
    }
    void add(int u, int v, ll cap) {
        edge.push_back(Edge(u, v, cap, 0));
        edge.push_back(Edge(v, u, 0, 0));
        int siz = edge.size();
        G[u].push_back(siz - 2);
        G[v].push_back(siz - 1);
    }
    void BFS() {
        for (int i = 1; i <= n; i++) dis[i] = n;
        queue<int> que;
        que.push(t);
        dis[t] = 0;
        while (que.size()) {
            int u = que.front();
            que.pop();
            for (int i = 0; i < G[u].size(); i++) {
                Edge &e = edge[G[u][i]];
                if (e.cap <= e.flow && dis[e.v] == n) {
                    que.push(e.v);
                    dis[e.v] = dis[u] + 1;
                }
            }
        }
    }
    ll Augment() {
        ll x = t, a = 0x3f3f3f3f;
        while (x != s) {
            Edge &e = edge[p[x]];
            a       = min(a, e.cap - e.flow);
            x       = edge[p[x]].u;
        }
        x = t;
        while (x != s) {
            edge[p[x]].flow += a;
            edge[p[x] ^ 1].flow -= a;
            x = edge[p[x]].u;
        }
        return a;
    }
    ll MaxFlow() {
        ll flow = 0LL;
        ///bfs();//wa
        BFS();//ac
        memset(num, 0, sizeof num);
        for (int i = 0; i <= n; i++) num[dis[i]]++;
        int x = s;
        memset(cur, 0, sizeof cur);
        while (dis[s] < n) {
            if (x == t) {
                flow += Augment();
                x = s;
            }
            int ok = 0;
            for (int i = cur[x]; i < G[x].size(); i++) {
                Edge &e = edge[G[x][i]];
                if (e.cap > e.flow && dis[x] == dis[e.v] + 1) {
                    ok     = 1;
                    p[e.v] = G[x][i];
                    cur[x] = i;
                    x      = e.v;
                    break;
                }
            }
            if (!ok) {
                ll m = n - 1;
                for (int i = 0; i < G[x].size(); i++) {
                    Edge &e = edge[G[x][i]];
                    if (e.cap > e.flow) m = min(m, dis[e.v]);
                }
                if (--num[dis[x]] == 0) break;
                num[dis[x] = m + 1]++;
                cur[x] = 0;
                if (x != s) x = edge[p[x]].u;
            }
        }
        return flow;
    }
} solve;
int main() {
    int n = read, m = read, s = read, t = read;
    solve.init(n, s, t);
    for (int i = 1; i <= m; i++) {
        int u = read, v = read;
        ll cap = read;
        solve.add(u, v, cap);
    }
    cout << solve.MaxFlow() << endl;
    return 0;
}
原文地址:https://www.cnblogs.com/PushyTao/p/15459799.html