Cod sursa(job #2462470)

Utilizator alex_HarryBabalau Alexandru alex_Harry Data 27 septembrie 2019 13:24:51
Problema Flux maxim de cost minim Scor 70
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.23 kb
#include <fstream>
#include <vector>
#include <queue>
#include <cstring>
using namespace std;
ifstream f("fmcm.in");
ofstream g("fmcm.out");
const int NMax = 355;
int N, M, S, Dest;
int D[355];
vector <pair <int, int> > G[NMax];
int Cap[30005], F[30005], Cost[30005], Rev[30005];
pair <int, int> E[30005];
int e;
pair <int, int> TT[30005];
bool InQ[355], Used[355];
int Dist[355], realD[355];
queue <int> Q;
priority_queue <pair <int, int>, vector <pair <int, int> >, greater <pair <int, int> > > PQ;
void addEdge(int x, int y, int cap, int cost){
    ++e;
    E[e] = make_pair(x, y);
    Rev[e] = e + 1;
    G[x].push_back(make_pair(y, e));
    Cost[e] = cost;
    Cap[e] = cap;
    F[e] = 0;
    ++e;
    E[e] = make_pair(y, x);
    Rev[e] = e - 1;
    G[y].push_back(make_pair(x, e));
    Cost[e] = -cost;
    Cap[e] = 0;
    F[e] = 0;
}
void Read(){
    f >> N >> M >> S >> Dest;
    for(int i = 1; i <= M; i++){
        int x, y, cap, cost;
        f >> x >> y >> cap >> cost;
        addEdge(x, y, cap, cost);
    }
}

void bellmanFord(int source){
    for(int i = 1; i <= N; i++)
        Dist[i] = 1000000005;
    Q.push(source);
    InQ[source] = 1;
    Dist[source] = 0;
    while(!Q.empty()){
        int node = Q.front();
        Q.pop();
        InQ[node] = 0;
        for(int i = 0; i < G[node].size(); i++){
            int neighb = G[node][i].first, cost = Cost[G[node][i].second];
            if(Dist[neighb] > Dist[node] + cost && Cap[G[node][i].second] != 0){
                Dist[neighb] = Dist[node] + cost;
                if(!InQ[neighb])
                    Q.push(neighb);
                InQ[neighb] = 1;
            }
        }
    }
}

bool Dijkstra(int source){
    for(int i = 1; i <= N; i++){
        D[i] = 1000000000;
        TT[i] = make_pair(-1, -1);
        //realD[i] = D[i];
    }

    D[source] = realD[source] = 0;
    PQ.push(make_pair(0, S));
    while(!PQ.empty()){
        int node = PQ.top().second, d = PQ.top().first;
        PQ.pop();
        if(d > D[node])
            continue;
        for(int i = 0; i < G[node].size(); i++){
            int neighb = G[node][i].first, e = G[node][i].second;
            if(Cap[e] - F[e] == 0)
                continue;
            int cost = Cost[e] + Dist[node] - Dist[neighb];
            if(D[node] + cost < D[neighb]){
                D[neighb] = D[node] + cost;
                realD[neighb] = realD[node] + Cost[e];
                TT[neighb] = make_pair(node, e);
                PQ.push(make_pair(D[neighb], neighb));
            }
        }
    }
    return TT[Dest] != make_pair(-1, -1);
}

void Solve(){
    int flow = 0;
    long long cost = 0;
    while(Dijkstra(S)){
        int Min = 2000000005;
        for(int i = Dest; i != S; i = TT[i].first){
            int e = TT[i].second;
            Min = min(Min, Cap[e] - F[e]);
        }
        cost += Min * realD[Dest];
        for(int i = Dest; i != S; i = TT[i].first){
            int e = TT[i].second, rev = Rev[e];
            F[e] += Min;
            F[rev] -= Min;
        }
        memcpy(Dist, realD, sizeof(realD));
    }
    g << cost << '\n';
}
int main()
{
    Read();
    bellmanFord(S);
    Solve();
    return 0;
}