网络流

与世无争的帅哥 提交于 2020-01-11 17:26:22
  • ISAP
#include <iostream>
#include <algorithm>
#include <queue>

namespace flow {
    const int N = 400000 + 7;
    const int INF = (1 << 30) - 1;
    
    struct flow {
        int n, m, st, ed;
        int lay[N], gap[N], cur[N], pre[N];
        struct edge {
            int to, nex, cap;
        } e[N];
        int fir[N], eid = 1;

        void addedge(int u, int v, int c);
        void addflow(int u, int v, int c);
        int isap();
    };
    
    void flow::addedge(int u, int v, int c) {
        e[++eid] = (edge){ v, fir[u], c }, fir[u] = eid;
    }
    void flow::addflow(int u, int v, int c) {
        addedge(u, v, c), addedge(v, u, 0);
    }
    
    int flow::isap() {
        std::queue <int> q; q.push(ed);
        for (int s; q.size(); ) {
            s = q.front(), q.pop();
            for (int i = fir[s]; i; i = e[i].nex)
                if (!lay[e[i].to] && e[i].to != ed && e[i ^ 1].cap)
                    lay[e[i].to] = lay[s] + 1, q.push(e[i].to);
        }
        for (int i = 1; i <= n; ++i) ++gap[lay[i]], cur[i] = fir[i];
            
        int maxflow = 0, s = st, ok;
        while (lay[st] < n) {
            if (s == ed) {
                int f = INF;
                while (s != st) s = pre[s], f = std::min(f, e[cur[s]].cap);
                s = ed, maxflow += f;
                while (s != st) s = pre[s], e[cur[s]].cap -= f, e[cur[s] ^ 1].cap += f;
            }
            ok = 0;
            for (int i = cur[s]; i; i = e[i].nex) {
                cur[s] = i;
                if (lay[s] == lay[e[i].to] + 1 && e[i].cap)
                    { pre[e[i].to] = s, s = e[i].to, ok = 1; break; }
            }
            if (ok) continue;
            if (!(--gap[lay[s]])) break;
            ++gap[++lay[s]], cur[s] = fir[s];
            if (s != st) s = pre[s];
        }
        return maxflow;
    }
};

int n, m, st, ed;
flow::flow f;

int main () {
    scanf("%d%d%d%d", &f.n, &f.m, &f.st, &f.ed);
    for (int i = 1, u, v, w; i <= f.m; ++i)
        scanf("%d%d%d", &u, &v, &w), f.addflow(u, v, w);
    printf("%d\n", f.isap());
    
    return 0;
}
  • SPFA
#include <iostream>
#include <queue>

using i64 = long long;

namespace flow {
    const int N = 5000 + 7, M = 50000 + 7;
    const i64 INF = 1ll << 30 - 1;

    struct flow {
        int n, st, ed;
        i64 mincost, maxflow;
        int cur[N], vis[N];
        i64 dis[N];
        struct edge {
            int to, nex;
            i64 cap, wei;
        } e[M << 1];
        int fir[N], eid = 1;

        void addedge(int u, int v, i64 c, i64 w);
        void addflow(int u, int v, i64 c, i64 w);
        i64 dinic();
        int bfs();
        i64 dfs(int s, i64 f);
    };

    void flow::addedge(int u, int v, i64 c, i64 w) {
        e[++eid] = (edge){ v, fir[u], c, w }, fir[u] = eid;
    }
    void flow::addflow(int u, int v, i64 c, i64 w) {
        addedge(u, v, c, w), addedge(v, u, 0, -w);
    }
    
    i64 flow::dinic() {
        maxflow = 0, mincost = 0;
        for (i64 f; bfs(); )
            while (1) {
                if (!(f = dfs(st, INF))) break;
                maxflow += f, mincost += f * dis[st];
            }
        return mincost;
    }
    int flow::bfs() {
        std::fill(dis + 1, dis + n + 1, INF);
        std::fill(vis + 1, vis + n + 1, 0);
        for (int i = 1; i <= n; ++i) cur[i] = fir[i];
        dis[ed] = 0, vis[ed] = 1;
        std::queue <int> q;
        q.push(ed);
        for (int s; q.size(); ) {
            s = q.front(), q.pop();
            for (int i = fir[s]; i; i = e[i].nex)
                if (e[i ^ 1].cap && dis[e[i].to] > dis[s] - e[i].wei) {
                    dis[e[i].to] = dis[s] - e[i].wei;
                    if (!vis[e[i].to]) vis[e[i].to] = 1, q.push(e[i].to);
                }
            vis[s] = 0;
        }
        return dis[st] < INF;
    }
    i64 flow::dfs(int s, i64 f) {
        if (s == ed) return f;
        vis[s] = 1;
        i64 t, u = 0;
        for (int i = cur[s]; i; i = e[i].nex) {
            cur[s] = i;
            if (!vis[e[i].to] && e[i].cap && dis[s] == dis[e[i].to] + e[i].wei) {
                t = dfs(e[i].to, std::min(f - u, e[i].cap));
                e[i].cap -= t, e[i ^ 1].cap += t;
                u += t;
                if (u == f) break;
            }
        }
        vis[s] = 0;
        return u;
    }
};

int m;
flow::flow f;

int main() {
    scanf("%d%d%d%d", &f.n, &m, &f.st, &f.ed);
    for (int i = 1, u, v, c, w; i <= m; ++i)
        scanf("%d%d%d%d", &u, &v, &c, &w), f.addflow(u, v, c, w);
    f.dinic();
    printf("%lld %lld\n", f.maxflow, f.mincost);
    
    return 0;
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!