Cod sursa(job #1408320)

Utilizator AlexandruValeanuAlexandru Valeanu AlexandruValeanu Data 29 martie 2015 23:31:46
Problema Flux maxim de cost minim Scor 70
Compilator cpp Status done
Runda Arhiva educationala Marime 4.36 kb
#include <bits/stdc++.h>

using namespace std;

const int Nmax = 350 + 1;
const int Mmax = 12500 + 1;

class MinCostMaxFlow
{
public:

    MinCostMaxFlow(const int N) : nrNodes(N), Graph(N, vector<int>(N)),
        Capacity(N, vector<int>(N)), Flow(N, vector<int>(N)), Cost(N, vector<int>(N)), dist(N), tata(N), in_queue(N) {
    }

    const int INF = numeric_limits<int>::max();

    struct Node
    {
        int nod;
        int dist;

        bool operator < (const Node& A) const
        {
            return dist > A.dist;
        }
    };

    int nrNodes;

    vector<vector<int>>Graph;
    vector<vector<int>>Capacity;
    vector<vector<int>>Flow;
    vector<vector<int>>Cost;

    queue<int> Q;
    priority_queue<Node> MinHeap;

    vector<int> dist;
    vector<int> tata;
    vector<bool> in_queue;

    void addEdge(int x, int y, int cap, int c)
    {
        Graph[x].push_back(y);
        Graph[y].push_back(x);

        Capacity[x][y] = cap;
        Capacity[y][x] = 0;

        Cost[x][y] = c;
        Cost[y][x] = -c;
    }

    bool Bellman_Ford(int S, int T)
    {
        for (int i = 0; i < nrNodes; ++i)
        {
            dist[i] = INF;
            in_queue[i] = false;
            tata[i] = -1;
        }

        Q.push(S);
        in_queue[S] = true;
        dist[S] = 0;
        tata[S] = S;

        while (Q.empty() == false)
        {
            int nod = Q.front();
            in_queue[nod] = false;
            Q.pop();

            for (int& son: Graph[nod])
            {
                if ((Capacity[nod][son] > Flow[nod][son]) && dist[son] > dist[nod] + Cost[nod][son])
                {
                    dist[son] = dist[nod] + Cost[nod][son];
                    tata[son] = nod;

                    if (!in_queue[son])
                    {
                        in_queue[son] = true;
                        Q.push(son);
                    }
                }
            }
        }

        return (dist[T] != INF);
    }

    void updateCosts()
    {
        for (int i = 0; i < nrNodes; ++i)
        {
            if (dist[i] != INF)
            {
                for (int& son: Graph[i])
                {
                    if (dist[son] != INF)
                        Cost[i][son] += (dist[i] - dist[son]);
                }
            }
        }
    }

    int Dijkstra(int S, int T)
    {
        updateCosts();

        for (int i = 0; i < nrNodes; ++i)
        {
            dist[i] = INF;
            tata[i] = -1;
        }

        MinHeap.push({S, 0});
        dist[S] = 0;
        tata[S] = S;

        while (MinHeap.empty() == false)
        {
            int nod = MinHeap.top().nod;
            int auxD = MinHeap.top().dist;
            MinHeap.pop();

            if (auxD != dist[nod])
                continue;

            for (int& son: Graph[nod])
            {
                if ((Capacity[nod][son] > Flow[nod][son]) && dist[son] > dist[nod] + Cost[nod][son])
                {
                    dist[son] = dist[nod] + Cost[nod][son];
                    tata[son] = nod;

                    MinHeap.push({son, dist[son]});
                }
            }
        }


        return (dist[T] != INF);
    }

    pair<int, long long> solve(int S, int T)
    {
        int flow = 0;
        long long costFlow = 0;
        long long totalDist = 0;

        Bellman_Ford(S, T);
        totalDist = dist[T];

        while (Dijkstra(S, T))
        {
            int fmin = INF;
            int nod = T;

            while (nod != S)
            {
                fmin = min(fmin, Capacity[ tata[nod] ][nod] - Flow[ tata[nod] ][nod]);
                nod = tata[nod];
            }

            nod = T;

            while (nod != S)
            {
                Flow[ tata[nod] ][nod] += fmin;
                Flow[nod][ tata[nod] ] -= fmin;
                nod = tata[nod];
            }

            flow += fmin;
            totalDist += dist[T];
            costFlow += (long long)fmin * totalDist;
        }

        return make_pair(flow, costFlow);
    }
};

int main()
{
    freopen("fmcm.in", "r", stdin);
    freopen("fmcm.out", "w", stdout);

    int N, M, S, T;
    scanf("%d %d %d %d", &N, &M, &S, &T);

    MinCostMaxFlow A(N + 1);

    for (int i = 0; i < M; ++i)
    {
        int x, y, cap, cost;
        scanf("%d %d %d %d", &x, &y, &cap, &cost);

        A.addEdge(x, y, cap, cost);
    }

    printf("%lld\n", A.solve(S, T).second);

    return 0;
}