Cod sursa(job #2255821)

Utilizator SqueekDanielTodasca Daniel SqueekDaniel Data 7 octombrie 2018 17:05:49
Problema Flux maxim de cost minim Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.15 kb
#include <bits/stdc++.h>

#define MaxN 355
#define inf  (1<<30)

std::ifstream InFile("fmcm.in");
std::ofstream OutFile("fmcm.out");

int N, M, S, D;
int FlowCost;
int Parent[MaxN], BFDist[MaxN];
int Dist[MaxN], Real_Dist[MaxN];
int Cost[MaxN][MaxN],
    Capacity[MaxN][MaxN],
    Flow[MaxN][MaxN];

std::vector <int> G[MaxN];

std::priority_queue <std::pair<int, int>, std::vector<std::pair<int, int>>, std::greater<std::pair<int, int>>> PQueue;
std::queue <int> Queue;
bool InQueue[MaxN];

inline void AddEdge(int x, int y, int c, int z) {
    Capacity[x][y] = c;
    Cost[x][y] = z;
    Cost[y][x] = -z;

    G[x].push_back(y);
    G[y].push_back(x);
}

void BellmanFord() {
    for (int i=0; i<N; ++i)
        BFDist[i] = inf;

    Queue.push(S);
    BFDist[S] = 0;
    InQueue[S] = 1;

    int Front;
    while (!Queue.empty()) {
        Front = Queue.front();
        Queue.pop();
        InQueue[Front] = 0;

        for (auto Vecin:G[Front]) {
            if (BFDist[Front] + Cost[Front][Vecin] < BFDist[Front] && Flow[Front][Vecin] < Capacity[Front][Vecin]) {
                BFDist[Vecin] = BFDist[Front] + Cost[Front][Vecin];
                if (!InQueue[Vecin]) {
                    InQueue[Vecin] = 1;
                    Queue.push(Vecin);
                }
            }
        }
    }
}

std::pair <int, int> Top;
inline bool Dijkstra() {
    for (int i=0; i<N; ++i)
        Dist[i+1] = inf,
        Real_Dist[i+1] = inf;

    PQueue.push({0, S});
    Real_Dist[S] = 0;
    Dist[S] = 0;

    while (!PQueue.empty()) {
        Top = PQueue.top();
        PQueue.pop();

        if (Dist[Top.second] < Top.first) continue;
        for (auto Vecin:G[Top.second]) {
            if (Dist[Top.second] +  Cost[Top.second][Vecin] + BFDist[Top.second] - BFDist[Vecin] < 1LL * Dist[Vecin] && Flow[Top.second][Vecin] < Capacity[Top.second][Vecin]) {
                Dist[Vecin] = Dist[Top.second] +  Cost[Top.second][Vecin] + BFDist[Top.second] - BFDist[Vecin];
                Real_Dist[Vecin] = Real_Dist[Top.second] + Cost[Top.second][Vecin];
                Parent[Vecin] = Top.second;
                PQueue.push({Dist[Vecin], Vecin});
            }
        }
    }

    for (int i=0; i<N; ++i)
        BFDist[i+1] = Real_Dist[i+1];

    if(Dist[D] == inf) return false;

        int minFlow = inf;
        for (auto Node = D; Node != S; Node = Parent[Node]) {
            minFlow = std::min(minFlow, Capacity[Parent[Node]][Node] - Flow[Parent[Node]][Node]);
        }

        if (minFlow > 0) {
            FlowCost += minFlow * Real_Dist[D];

            for (auto Node = D; Node != S; Node = Parent[Node]) {
                Flow[Parent[Node]][Node] += minFlow;
                Flow[Node][Parent[Node]] -= minFlow;
            }
        }

    return true;
}

void Rezolvare() {
    BellmanFord();
    while (Dijkstra());

    OutFile << FlowCost << "\n";
}

void Citire() {
    InFile >> N >> M >> S >> D;
    for (int i=0, x, y, c, z; i<M; ++i) {
        InFile >> x >> y >> c >> z;
        AddEdge(x, y, c, z);
    }
}

int main() {
    Citire();
    Rezolvare();

    return 0;
}