Cod sursa(job #2939702)

Utilizator Fantastic_Mantudor voicu Fantastic_Man Data 14 noiembrie 2022 00:20:37
Problema Flux maxim de cost minim Scor 30
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.97 kb
#include <fstream>
#include <vector>
#include <queue>
using namespace std;
const int nmax = 350;
const int oo = 1e9;

vector < int > g[nmax + 1];
int cap[nmax + 1][nmax + 1];
int cost[nmax + 1][nmax + 1];
int dist[nmax + 1];
int real_dist[nmax + 1];
int fake_dist[nmax + 1];
bool inQ[nmax + 1];
int vis[nmax + 1];
int p[nmax + 1];

int n, source, sink;

void add_edge ( int x, int y, int c, int z ) {
    g[x].push_back ( y );
    g[y].push_back ( x );
    cap[x][y] = c;
    cost[x][y] = z;
    cost[y][x] = -z;
}

int bellman ( int start = source ) {
    for ( int i = 1; i <= n; i++ )
        dist[i] = oo;

    queue < int > q;

    inQ[start] = 1;
    q.push ( start );
    dist[start] = true;
    while ( ! q.empty () ) {
        int node = q.front ();
        q.pop ();
        inQ[node] = false;
        for ( int x: g[node] )
            if ( cap[node][x] > 0 && dist[x] < dist[node] + cost[node][x] ) {
                dist[x] = dist[node] + cost[node][x];
                if ( inQ[x] == false ) {
                    inQ[x] = true;
                    q.push ( x );
                }
            }
    }
    return ( dist[sink] != oo );
}

int dijkstra ( int start = source ) {
    priority_queue < pair < int, int > > pq;
    for ( int i = 1; i <= n; i++ ) {
        vis[i] = 0, p[i] = 0;
        real_dist[i] = dist[i];
        fake_dist[i] = oo;
    }
    p[start] = 0;
    dist[start] = fake_dist[start] = 0;
    pq.push ( { 0, start } );
    while ( ! pq.empty () ) {
        int node = pq.top ().second;
        pq.pop ();
        if ( vis[node] == 0 ) {
            vis[node] = 1;
            for ( int x: g[node] )
                if ( cap[node][x] > 0 && ( p[x] == 0 || fake_dist[x] > fake_dist[node] + real_dist[node] + cost[node][x] - real_dist[x] ) ) {
                    fake_dist[x] = fake_dist[node] + real_dist[node] + cost[node][x] - real_dist[x];
                    dist[x] = dist[node] + cost[node][x];
                    p[x] = node;
                    pq.push ( { -fake_dist[x], x } );
                }
        }
    }
    return fake_dist[sink] != oo;
}

int min_cost_flow () {
    int CostTotal = 0;
    bellman ();
    while ( dijkstra () ) {
        int node = sink, flow = oo, Cost = 0;
        while ( node != source )
            flow = min ( flow, cap[p[node]][node] ),
            Cost += cost[p[node]][node],
            node = p[node];

        node = sink;
        while ( node != source ) {
            cap[p[node]][node] -= flow;
            cap[node][p[node]] += flow;
            node = p[node];
        }

        CostTotal += Cost * flow;
    }
    return CostTotal;
}

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

int main() {
    int m, x, y, c, z;
    fin >> n >> m >> source >> sink;

    for ( int i = 1; i <= m; i++ ) {
        fin >> x >> y >> c >> z;
        add_edge ( x, y, c, z );
    }

    fout << min_cost_flow () << '\n';


    return 0;
}