Cod sursa(job #2573950)

Utilizator nurof3nCioc Alex-Andrei nurof3n Data 5 martie 2020 19:39:42
Problema Flux maxim de cost minim Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.54 kb
#include <fstream>
#include <vector>
#include <queue>

using namespace std;

ifstream in( "fmcm.in" );
ofstream out( "fmcm.out" );

const int N_MAX = 350;
const int INF = 1000000000;

struct comp {
    bool operator()( const pair<int, int> &a, const pair<int, int> &b ) {
        return a.second > b.second;
    }
};

int N, M, Source, Dest;
vector<int> Edges[N_MAX + 1];
int Capacity[N_MAX + 1][N_MAX + 1], Cost[N_MAX + 1][N_MAX + 1], Flow[N_MAX + 1][N_MAX + 1];

priority_queue<pair<int, int>, vector<pair<int, int>>, comp> Q;
int D[N_MAX + 1];
int oldD[N_MAX + 1];
int realD[N_MAX + 1];
int T[N_MAX + 1];
bool inQ[N_MAX + 1];

void SPFA() {
    for ( int i = 1; i <= N; i++ )
        oldD[i] = INF;
    oldD[Source] = 0;

    queue<int> Q;
    Q.push( Source ), inQ[Source] = true;

    while ( !Q.empty() ) {
        int x = Q.front();
        Q.pop();
        inQ[x] = false;
        for ( auto y : Edges[x] )
            if ( Capacity[x][y] ) { //! sa fie arc din graful normal
                int cost = Cost[x][y];
                if ( oldD[x] + cost < oldD[y] ) {
                    oldD[y] = oldD[x] + cost;
                    if ( !inQ[y] ) {
                        Q.push( y );
                        inQ[y] = true;
                    }
                }
            }
    }
}

bool dijkstra() {
    for ( int i = 1; i <= N; i++ )
        D[i] = INF;
    D[Source] = 0, realD[Source] = 0;

    Q.push( pair<int, int>( Source, D[Source] ) );
    while ( !Q.empty() ) {
        int x = Q.top().first, cst = Q.top().second;
        Q.pop();
        if ( D[x] != cst )
            continue;
        for ( auto y : Edges[x] )
            if( Capacity[x][y] > Flow[x][y] ) {
                int cost = Cost[x][y];
                int newD = D[x] + oldD[x] - oldD[y];
                if ( newD + cost < D[y] ) {
                    D[y] = newD + cost;
                    realD[y] = realD[x] + cost;
                    T[y] = x;
                    Q.push( pair<int, int>( y, D[y] ) );
                }
            }
    }

    if ( D[Dest] == INF ) //daca nu am ajuns in Dest, nu mai avem ce ameliora, avem flux maxim de cost minim
        return false;
    return true;
}

int main() {
    int x, y, cap, cost;
    in >> N >> M >> Source >> Dest;
    for ( int i = 1; i <= M; ++i ) {
        in >> x >> y >> cap >> cost;
        Edges[x].push_back( y );
        Capacity[x][y] = cap;
        Cost[x][y] = cost;
        //formam graful rezidual: se adauga arcele inverse, cu capacitatea 0 si costul -cost
        Edges[y].push_back( x );
        Capacity[y][x] = 0;
        Cost[y][x] = -cost;
    }

    //graful rezidual contine arce de cost negativ, deci aplicam initial algoritmul Bellman-Ford, dar pe graful normal
    SPFA();

    int maxflow = 0, mincost = 0;
    while ( dijkstra() ) {
        int flowgap = INF;
        for ( int x = Dest; x != Source; x = T[x] ) //parcurgem invers lantul de ameliorare si determinam capacitatea reziduala minima
            flowgap = min( flowgap, Capacity[T[x]][x] - Flow[T[x]][x] );

        //amelioram fluxul lantului
        for ( int x = Dest; x != Source; x = T[x] ) {
            mincost += Cost[T[x]][x] * flowgap;
            Flow[T[x]][x] += flowgap;  //se creste fluxul pe arcele retelei de transport
            Flow[x][T[x]] -= flowgap;  //se scade fluxul pe arcele grafului rezidual
        }
        maxflow += flowgap;
        for ( int i = 1; i <= N; ++i )
            oldD[i] = realD[i];
    }

    out << mincost;

    return 0;
}