Cod sursa(job #1870074)

Utilizator borcanirobertBorcani Robert borcanirobert Data 6 februarie 2017 12:57:54
Problema Flux maxim de cost minim Scor 70
Compilator cpp Status done
Runda Arhiva educationala Marime 2.8 kb
/// Calcularea costului minim pt. a obtine un flux maxim pe un graf orientat

#include <fstream>
#include <vector>
#include <queue>
#include <algorithm>
#include <iostream>
#include <cstring>
using namespace std;

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

const int MAX = 355;
const int Inf = 0x3f3f3f3f;
struct Nod{
    int cost, nod;

    bool operator < ( const Nod& a ) const
    {
        return cost > a.cost;
    }
};
using VI = vector<int>;
vector<VI> G;
int N, M, S, D;
int m[MAX][MAX];
int C[MAX][MAX];
int Cost[MAX]; /// costul curent
int P[MAX];    /// costul precedent
int RealCost[MAX];    /// costul curent real
int t[MAX];
int cmin;

void ReadGraph();
void Bellman_Ford();
bool Dijkstra();

int main()
{
    ReadGraph();

    Bellman_Ford();

  /*  for ( int i = 1; i <= N; ++i )
        fout << P[i] << ' ';    */

    while ( Dijkstra() );

    fout << cmin << '\n';

    fin.close();
    fout.close();
    return 0;
}

void ReadGraph()
{
    int x, y, z, t;

    fin >> N >> M >> S >> D;
    G = vector<VI>(N + 1);
    while ( M-- )
    {
        fin >> x >> y >> z >> t;

        G[x].push_back(y);
        G[y].push_back(x);
        m[x][y] = t;
        m[y][x] = -t;

        C[x][y] = z;
        C[y][x] = 0;
    }
}

void Bellman_Ford()
{
    queue<int> Q;

    memset( P, Inf, sizeof(P) );

    P[S] = 0;
    Q.push(S);

    while ( !Q.empty() )
    {
        int x = Q.front();
        Q.pop();

        for ( const int& y : G[x] )
            if ( C[x][y] )
            {
                int cost_nou = P[x] + m[x][y];

                if ( cost_nou >= P[y] )
                    continue;

                P[y] = cost_nou;
                Q.push(y);
            }
    }
}

bool Dijkstra()
{
    priority_queue<Nod> Q;
    memset(Cost, Inf, sizeof(Cost));

    Cost[S] = RealCost[S] = 0;
    Q.push({0, S});

    while ( !Q.empty() )
    {
        int x = Q.top().nod;
        int c0 = Q.top().cost;
        Q.pop();

        if ( c0 != Cost[x] ) continue;

        for ( const int& y : G[x] )
            if ( C[x][y] )
            {
                int cost_nou = Cost[x] + P[x] + m[x][y] - P[y];

                if ( cost_nou >= Cost[y] )
                    continue;

                Cost[y] = cost_nou;
                RealCost[y] = RealCost[x] + m[x][y];
                t[y] = x;

                Q.push({Cost[y], y});
            }
    }
    memcpy(P, Cost, sizeof(Cost));

    if ( Cost[D] >= Inf ) return false;

    int fc = Inf;
    for ( int i = D; i != S; i = t[i] )
        fc = min( fc, C[t[i]][i] );

    cmin += fc * RealCost[D];
    for ( int i = D; i != S; i = t[i] )
    {
        C[t[i]][i] -= fc;
        C[i][t[i]] += fc;
    }

    return true;
}