Cod sursa(job #2255847)

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

#define MaxN 355
#define inf  (int)(1e9)

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

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

class DirectedGraph {
public:
    int FlowCost;
    int N;

    inline void AddEdge(int x, int y, int c, int z) {
        Node[x].ADC.push_back(y);
        Node[y].ADC.push_back(x);
        Capacity[x][y] = c;
        Cost[y][x] = -z;
        Cost[x][y] = z;
    }

    inline bool Dijkstra() {
        for (int i=0; i<N; ++i)
            Dist[i+1] = inf,
            RealDist[i+1] = inf;

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

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

            if (Dist[Top.second] < Top.first) continue;
            for (auto Vecin:Node[Top.second].ADC)
                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];
                    RealDist[Vecin] = RealDist[Top.second] + Cost[Top.second][Vecin];
                    Parent[Vecin] = Top.second;
                    PQueue.push({Dist[Vecin], Vecin});
                }
        }

        for (int i=0; i<N; ++i)             // !!!!!!!!!!!!!!!!!!! SUPER SUPER SUPER SUPER SUPER SUPER SUPER SUPER IMPORTANT !!!!!!!!!!!!!!!!!!!
            BFDist[i+1] = RealDist[i+1];
        if(Dist[D] == inf) return false;

        int MinFlow = inf, x = D;
        while (x!=S)
            MinFlow = std::min(MinFlow, Capacity[Parent[x]][x] - Flow[Parent[x]][x]),
            x = Parent[x];
        if (MinFlow <= 0) return true;

        x = D;
        FlowCost += MinFlow * RealDist[D];
        while (x!=S)
            Flow[x][Parent[x]] -= MinFlow,
            Flow[Parent[x]][x] += MinFlow,
            x = Parent[x];
        return true;
    }

    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:Node[Front].ADC)
                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);
                }
        }
    }

private:
    int Parent[MaxN];
    int BFDist[MaxN],
        Dist[MaxN],
        RealDist[MaxN];
    int Cost[MaxN][MaxN],
        Capacity[MaxN][MaxN],
        Flow[MaxN][MaxN];

    struct GraphNode {
        std::vector <int> ADC;
    }   Node[MaxN];

}   Graph;

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

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

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

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

    return 0;
}