最小費用フローテンプレート

2679 ワード

#include <iostream>

#include <cstring>

#include <cstdio>

#include <algorithm>

using namespace std;



 



class mincost

{

private:

    const static int V = 1001;

    const static int E = 1000001;

    const static int INF = -1u >> 1;



    struct Edge

    {

        int v, cap, cost;

        Edge *next;

    } pool[E], *g[V], *pp, *pree[V];

    int T, S, dis[V], pre[V];

    int n, m, flow, cirq[V];

    void SPFA();

    inline void addedge(int i, int j, int cap, int cost);

public:

    bool initialize();

    void mincost_maxflow();

};



void mincost::mincost_maxflow()

{

    while (true)

    {

        SPFA();

        if (dis[T] == INF)

            break;

        int minn = INF;

        for (int i = T; i != S; i = pre[i])

            minn = min(minn, pree[i]->cap);

        for (int i = T; i != S; i = pre[i])

        {

            pree[i]->cap -= minn;

            pool[(pree[i] - pool)^0x1].cap += minn;

            flow += minn * pree[i]->cost;

        }

    }

    printf("%d
", flow); } void mincost::SPFA() { bool vst[V] = {false}; int tail = 0, u; fill(dis,dis + n,0x7fffffff); cirq[0] = S; vst[S] = 1; dis[S] = 0; for (int i = 0; i <= tail; i++) { int v = cirq[i % n]; for (Edge *i = g[v]; i != NULL; i = i->next) { if (!i->cap) continue; u = i->v; if (i->cost + dis[v] < dis[u]) { dis[u] = i->cost + dis[v]; pree[u] = i; pre[u] = v; if (!vst[u]) { tail++; cirq[tail % n] = u; vst[u] = true; } } } vst[v] = false; } } void mincost::addedge(int i, int j, int cap, int cost) { pp->cap = cap; pp->v = j; pp->cost = cost; pp->next = g[i]; g[i] = pp++; } bool mincost::initialize() { memset(g, 0, sizeof (g)); pp = pool; scanf("%*s %*d"); scanf("%d %d %d %d", &n, &m, &S, &T); int v, u, f, c; for (int i = 0; i < m; i++) { scanf("%d %d %d %d", &v, &u, &f, &c); addedge(v, u, f, c); addedge(u, v, 0, -c); } flow = 0; return true; } mincost g; int main() { int t; scanf("%d", &t); while (t--) { g.initialize(); g.mincost_maxflow(); } return 0; }