费用流

Dijkstra 费用流

#include <cstdio>
#include <climits>
#include <vector>
#include <queue>
#include <algorithm>

const int MAXN = 405;

struct Edge;
struct Node;

struct Node {
    std::vector<Edge> e;
    Edge *pre;
    int flow, h, dist;
} N[MAXN];

struct Edge {
    Node *u, *v;
    int cap, flow, cost, rev;

    Edge(Node *u, Node *v, int cap, int cost, int rev) : u(u), v(v), rev(rev), cap(cap), flow(0), cost(cost) {}
};

void addEdge(int u, int v, int cap, int cost) {
    N[u].e.push_back(Edge(&N[u], &N[v], cap, cost, N[v].e.size()));
    N[v].e.push_back(Edge(&N[v], &N[u], 0, -cost, N[u].e.size() - 1));
}

namespace EdmondsKarp {
    struct HeapNode {
        Node *u;
        int dist;

        HeapNode(Node *u, int dist) : u(u), dist(dist) {}

        bool operator<(const HeapNode &rhs) const {
            return dist > rhs.dist;
        }
    };

    void solve(int s, int t, int n, int &flow, int &cost) {
        flow = cost = 0;
        // if there exists negative cost, run bellman-ford on h[] first
        while (true) {
            for (int i = 1; i <= n; i++) {
                N[i].dist = INT_MAX;
                N[i].flow = 0;
                N[i].pre = NULL;
            }

            std::priority_queue<HeapNode> q;
            q.push(HeapNode(&N[s], 0));

            N[s].dist = 0;
            N[s].flow = INT_MAX;

            while (!q.empty()) {
                HeapNode un = q.top();
                q.pop();
                Node *u = un.u;

                if (u->dist != un.dist) continue;

                for (Edge *e = &u->e.front(); e <= &u->e.back(); e++) {
                    int newCost = e->cost + u->h - e->v->h;
                    if (e->cap > e->flow && e->v->dist > u->dist + newCost) {
                        e->v->dist = u->dist + newCost;
                        e->v->flow = std::min(u->flow, e->cap - e->flow);
                        e->v->pre = e;

                        q.push(HeapNode(e->v, e->v->dist));
                    }
                }
            }

            if (N[t].dist == INT_MAX) break; // minimum cost maximum flow
            // if (N[t].dist + N[t].h > 0) break; // minimum cost available flow

            for (int i = 1; i <= n; i++) N[i].h = std::min(N[i].h + N[i].dist, INT_MAX >> 1);

            for (Edge *e = N[t].pre; e; e = e->u->pre) {
                e->flow += N[t].flow;
                e->v->e[e->rev].flow -= N[t].flow;
            }

            flow += N[t].flow;
            cost += N[t].h * N[t].flow;
        }
    }
}

int main() {
    int n, m;
    scanf("%d %d", &n, &m);

    for (int i = 0, u, v, c, w; i < m; i++) {
        scanf("%d %d %d %d", &u, &v, &c, &w);
        addEdge(u, v, c, w);
    }

    int flow, cost;
    EdmondsKarp::solve(1, n, n, flow, cost);
    printf("%d %d\n", flow, cost);

    return 0;
}

ZKW 费用流

#include <cstdio>
#include <climits>
#include <queue>
#include <algorithm>

const int MAXN = 405;

struct Graph {
    struct Edge {
        int v, cap, flow, cost, rev;

        Edge(int v, int cap, int cost, int rev) : v(v), cap(cap), flow(0), cost(cost), rev(rev) {}
    };

    void addEdge(int u, int v, int cap, int cost) {
        G[u].emplace_back(v, cap, cost, G[v].size());
        G[v].emplace_back(u, 0, -cost, G[u].size() - 1);
    }

    std::vector<Edge> G[MAXN];
    int n;
} G;

class MCMF {
public:
    std::pair<int, int> solve(int s, int t, Graph &G) {
        this->s = s;
        this->t = t;
        this->G = &G;

        int flow = 0, cost = 0;
        int rem = INT_MAX;
        while (argument()) {
            std::fill_n(ptr + 1, G.n, 0);
            int d = dfs(s, rem - flow);
            flow += d;
            cost += d * dist[t];
        }

        return std::make_pair(flow, cost);
    }

private:
    int s, t;
    Graph *G;
    int dist[MAXN], ptr[MAXN];
    bool vis[MAXN];

    bool argument() {
        std::fill_n(dist + 1, G->n, INT_MAX);
        std::fill_n(vis + 1, G->n, false);
        dist[s] = 0;

        std::queue<int> q;
        q.push(s);
        while (!q.empty()) {
            int u = q.front();
            q.pop();

            vis[u] = false;
            for (auto &e : G->G[u]) {
                if (e.cap > e.flow && dist[e.v] > dist[u] + e.cost) {
                    dist[e.v] = dist[u] + e.cost;
                    if (!vis[e.v]) {
                        vis[e.v] = true;
                        q.push(e.v);
                    }
                }
            }
        }

        return dist[t] != INT_MAX;
    }

    int dfs(int u, int r) {
        if (u == t) return r;

        vis[u] = true;
        int res = 0;

        for (int &i = ptr[u]; i < G->G[u].size(); i++) {
            auto &e = G->G[u][i];
            if (e.cap > e.flow && dist[e.v] == dist[u] + e.cost && !vis[e.v]) {
                int d = dfs(e.v, std::min(r - res, e.cap - e.flow));
                res += d;
                e.flow += d;
                G->G[e.v][e.rev].flow -= d;
                if (res == r) {
                    vis[u] = false;
                    break;
                }
            }
        }

        return res;
    }
} mcmf;

int main() {
    int n, m;
    scanf("%d %d", &n, &m);

    G.n = n;
    for (int i = 0, u, v, c, w; i < m; i++) {
        scanf("%d %d %d %d", &u, &v, &c, &w);
        G.addEdge(u, v, c, w);
    }

    auto [flow, cost] = mcmf.solve(1, n, G);
    printf("%d %d\n", flow, cost);

    return 0;
}

results matching ""

    No results matching ""