Cod sursa(job #1937671)

Utilizator iulian_f2kGuraliuc Iulian iulian_f2k Data 24 martie 2017 09:31:45
Problema Flux maxim de cost minim Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.13 kb
#include <iostream>
#include <fstream>
#include <climits>
#include <vector>
#include <algorithm>
#include <queue>
using namespace std;

const int NMAX = 355;
int N, M, Source, Dest, maxFlow = INT_MIN, Flow[NMAX][NMAX], Capacity[NMAX][NMAX], costMin;
int Cost[NMAX][NMAX], distBF[NMAX], DijDist[NMAX], realD[NMAX], Father[NMAX];
vector<int> G[NMAX];

void Read();
void BellmanFord();
void FMCM();
void Write() {  cout << costMin << '\n';    }
int main() {
    Read();
    FMCM();
    Write();
}

void Read() {
    freopen("fmcm.in", "rt", stdin);
    freopen("fmcm.out", "wt", stdout);
    scanf("%d%d%d%d", &N, &M, &Source, &Dest);
    while(M--) {
        int u, v, cap, cost;
        scanf("%d%d%d%d", &u, &v, &cap, &cost);
        G[u].push_back(v);      G[v].push_back(u);
        Cost[u][v] = cost;      Cost[v][u] = -cost;
        Capacity[u][v] += cap;
    }
}

void BellmanFord() {
    for(int i = 0; i <= N; i++)         distBF[i] = INT_MAX;
    queue<int> Q;   Q.push(Source);     distBF[Source] = 0;
    vector<bool> inQueue(N + 1, 0);
    while(!Q.empty()) {
        int node = Q.front();
        Q.pop();    inQueue[node] = false;
        for(int i = 0; i < G[node].size(); i++) {
            int neigh = G[node][i];
            if(!Capacity[node][neigh])  continue;
            if(distBF[neigh] > distBF[node] + Cost[node][neigh]) {
                distBF[neigh] = distBF[node] + Cost[node][neigh];
                if(!inQueue[neigh]) {
                    Q.push(neigh);      inQueue[neigh] = true;
                }
            }
        }
    }
}

void Dijkstra() {
    priority_queue<pair<int, int>, vector<pair<int, int> >, greater<pair<int, int> > > PQ;
    for(int i = 0; i <= N; i++)     DijDist[i] = INT_MAX,    Father[i] = -1;
    DijDist[Source] = realD[Source] = 0;
    PQ.push(make_pair(0, Source));
    while(!PQ.empty()) {
        pair<int, int> top = PQ.top();  PQ.pop();
        int node = top.second, d = top.first;
        if(DijDist[node] < d)    continue;
        for(int i = 0; i < G[node].size(); i++) {
            int neigh = G[node][i];
            if(Capacity[node][neigh] > Flow[node][neigh]) {
                int artificiu = Cost[node][neigh] + distBF[node] - distBF[neigh];
                if(d + artificiu < DijDist[neigh]) {
                    DijDist[neigh] = d + artificiu;
                    PQ.push(make_pair(DijDist[neigh], neigh));
                    realD[neigh] = realD[node] + Cost[node][neigh];
                    Father[neigh] = node;
                }
            }
        }
    }
}

void FMCM() {
    BellmanFord();
    while(1) {
        Dijkstra();
        if(Father[Dest] == -1)   break;
        int mn = INT_MAX;
        for(int node = Dest; node != Source; node = Father[node])
            mn = min(mn, Capacity[Father[node]][node] - Flow[Father[node]][node]);
            maxFlow += mn;
        costMin += mn * realD[Dest];
        for(int node = Dest; node != Source; node = Father[node])
            Flow[Father[node]][node] += mn,     Flow[node][Father[node]] -= mn;
        for(int i = 0; i <= N; i++)     distBF[i] = realD[i];
    }
}