Cod sursa(job #2959747)

Utilizator alex_bb8Banilean Alexandru-Ioan alex_bb8 Data 2 ianuarie 2023 16:19:50
Problema Flux maxim de cost minim Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.47 kb
#include <bits/stdc++.h>

using namespace std;

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

const int NMAX = 355;

int N, M, S, D;
vector<int> G[NMAX];
vector<vector<int>> capacity(NMAX, vector<int> (NMAX, 0));
vector<vector<int>> cost(NMAX, vector<int> (NMAX, 0));
vector<int> dist(NMAX, 0);

void read(){

    f >> N >> M >> S >> D;

    for(int i = 1; i <= M; ++i){
        int x, y, z, c;
        f >> x >> y >> z >> c;
        G[x].push_back(y);
        G[y].push_back(x);

        capacity[x][y] = z;

        cost[x][y] = c;
        cost[y][x] = -c;
    }

}

void BellmanFordFast(){
    dist.assign(N + 1, INT_MAX);

    //vector<int> cnt(N, 0);
    vector<bool> in_queue(N + 1, false);
    queue<int> Q;

    dist[S] = 0;
    in_queue[S] = true;
    Q.push(S);

    while(!Q.empty()){
        int node = Q.front();
        Q.pop();
        in_queue[node] = false;

        for(auto& next : G[node]){
            if(capacity[node][next] > 0 && dist[node] + cost[node][next] < dist[next]){
                dist[next] = dist[node] + cost[node][next];

                if(!in_queue[next]){
                    Q.push(next);
                    in_queue[next] = true;
                    //++cnt[next];

                    //if(cnt[next] > N)
                    //    return false; // negative cycle
                }
            }
        }
    }

    //return true;
}

bool Dijkstra(vector<int>& parent){

    vector<int> aux_dist(N + 1, INT_MAX), real_dist(N + 1, INT_MAX);
    priority_queue<pair<int, int>> PQ;

    parent[S] = -1;
    aux_dist[S] = real_dist[S] = 0;
    PQ.push({0, S});

    while(!PQ.empty()){
        int node_cst = -PQ.top().first;
        int node = PQ.top().second;
        PQ.pop();

        if(aux_dist[node] != node_cst)
            continue;

        for(auto& next : G[node]){
            if(capacity[node][next] > 0){
                int temp_dist = aux_dist[node] +
                                cost[node][next] +
                                dist[node] - dist[next];

                if(temp_dist < aux_dist[next]){
                    aux_dist[next] = temp_dist;
                    real_dist[next] = real_dist[node] + cost[node][next];
                    parent[next] = node;
                    PQ.push({-aux_dist[next], next});
                }
            }
        }   
    }
    
    for(int i = 1; i <= N; ++i)
        dist[i] = real_dist[i];
        
    return (aux_dist[D] != INT_MAX);
}

void solve(){
    
    int max_flow = 0, min_cost = 0;
    vector<int> parent(NMAX, -1);
    
    BellmanFordFast(); // initialize
    
    while(Dijkstra(parent)){
        
        int path_flow = INT_MAX, path_cost = 0;
        
        // find the max flow through the path
        for(int node = D; node != S; node = parent[node]){
            int aux = parent[node];
            path_flow = min(path_flow, capacity[aux][node]);
            path_cost += cost[aux][node];
        }
        
        //if(path_flow == 0) continue;
        
        // update
        for(int node = D; node != S; node = parent[node]){
            int aux = parent[node];
            capacity[aux][node] -= path_flow;
            capacity[node][aux] += path_flow;
        }
        
        max_flow += path_flow;
        min_cost += path_flow * path_cost;

    }
    
    g << min_cost << '\n';
    
}

int main(){
    
    read();
    
    solve();

    return 0;
}