Cod sursa(job #2939723)

Utilizator Fantastic_Mantudor voicu Fantastic_Man Data 14 noiembrie 2022 01:02:09
Problema Flux maxim de cost minim Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.16 kb
#include <fstream>
#include <vector>
#include <queue>
#include <algorithm>
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];

bool inQ[nmax + 1];

int dist[nmax + 1];
int real_dist[nmax + 1];
int fake_dist[nmax + 1];
bool 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] = -1;
    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;
}

ofstream fout ( "fmcm.out" );
int min_cost_flow ( int source, int sink ) {
    int CostTotal = 0;
    bellman ( source );
    while ( dijkstra ( source ) ) {
        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" );

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 );
    }

    for ( int i = 1; i <= n; i++ )
        random_shuffle ( g[i].begin (), g[i].end () );

    fout << min_cost_flow ( source, sink ) << '\n';


    return 0;
}