Cod sursa(job #3224997)

Utilizator Tudor06MusatTudor Tudor06 Data 16 aprilie 2024 19:17:14
Problema Flux maxim de cost minim Scor 20
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.91 kb
#include <bits/stdc++.h>
#pragma GCC target( "avx2" )

using namespace std;

const int INF = 1e9;

struct Dinic {
    int n;
    struct edge {
        int from;
        int to;
        int cost;
        int cap;
    };
    vector <edge> muchii;
    vector<vector <int>> edges;
    vector <bool> viz;
    vector <int> prv;
    vector <int> dist;

    void init( int N ) {
        n = N;
        edges.resize( n );
        viz.resize( n );
        dist.resize( n );
        prv.resize( n );
    }

    void addEdge( int from, int to, int cost, int cap ) {
        edges[from].push_back( muchii.size() );
        muchii.push_back( (edge){ from, to, cost, cap } );

        edges[to].push_back( muchii.size() );
        muchii.push_back( (edge){ to, from, -cost, 0 } );
    }
    bool bellman( int source, int dest ) {
        queue <int> q;
        vector <int> deg(n, 0);
        for ( int i = 0; i < n; i ++ ) dist[i] = INF;
        dist[source] = 0;
        for ( auto e : muchii ) if ( e.cap ) deg[e.to] ++;
        for ( int i = 0; i < n; i ++ ) if ( !deg[i] ) q.push( i );
        while ( !q.empty() ) {
            int node = q.front();
            q.pop();
            for ( auto i : edges[node] ) {
                auto e = muchii[i];
                if ( e.cap ) {
                    dist[e.to] = min( dist[e.to], dist[node] + e.cost );
                    deg[e.to] --;
                    if ( !deg[e.to] ) q.push( e.to );
                }
            }
        }
        return dist[dest] != INF;
    }
    bool dijkstra( int source, int dest ) {
        vector <bool> viz( n, 0 );
        vector <int> fakeDist( n, INF );
        vector <int> realDist( n );
        for ( int i = 0; i < n; i ++ ) {
            realDist[i] = dist[i];
            prv[i] = -1;
        }
        priority_queue <pair<int, int>> pq;
        pq.push( { 0, source } );
        dist[source] = fakeDist[source] = 0;
        while ( !pq.empty() ) {
            int node = pq.top().second;
            pq.pop();
            if ( !viz[node] ) {
                viz[node] = true;
                for ( auto i : edges[node] ) {
                    edge e = muchii[i];
                    if ( e.cap && fakeDist[node] + realDist[node] + e.cost - realDist[e.to] < fakeDist[e.to] ) {
                        fakeDist[e.to] = fakeDist[node] + realDist[node] + e.cost - realDist[e.to];
                        dist[e.to] = dist[node] + e.cost;
                        prv[e.to] = i;
                        pq.push( { -fakeDist[e.to], e.to } );
                    }
                }
            }
        }
        return fakeDist[dest] != INF;
    }
    pair <int, int> push( int source, int dest ) {
        int flow = INF, c = 0;
        for ( int node = dest; node != source; node = muchii[prv[node]].from ) {
            flow = min( flow, muchii[prv[node]].cap );
            c += muchii[prv[node]].cost;
        }
        for ( int node = dest; node != source; node = muchii[prv[node]].from ) {
            muchii[prv[node]].cap -= flow;
            muchii[prv[node]^1].cap += flow;
        }
        return {flow, flow * c};
    }

    pair <int, int> maxFlowMinCost( int source, int dest ) {
        int maxFlow = 0, minCost = 0;
        if ( !bellman( source, dest ) ) return { 0, 0 };
        while ( dijkstra( source, dest ) ) {
            auto p = push( source, dest );
            maxFlow += p.first;
            minCost += p.second;
        }
        return { maxFlow, minCost };
    }
};


int main() {
    ifstream fin( "fmcm.in" );
    ofstream fout( "fmcm.out" );
    int n, m, s, d;
    fin >> n >> m >> s >> d;
    Dinic graph;
    graph.init( n );
    for ( int i = 0, from, to, cap, cost; i < m; i ++ ) {
        fin >> from >> to >> cap >> cost;
        graph.addEdge( from - 1, to - 1, cost, cap );
    }
    fout << graph.maxFlowMinCost( s - 1, d - 1 ).second;
    return 0;
}