Cod sursa(job #2959742)

Utilizator alex_bb8Banilean Alexandru-Ioan alex_bb8 Data 2 ianuarie 2023 16:10:25
Problema Flux maxim de cost minim Scor 20
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.56 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<pair<int, int>> G[NMAX]; // graph with costs
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, c});
        
        capacity[x][y] = z;
        
        cost[x][y] = c;
        cost[y][x] = -c;
    }
    
}

void BellmanFordFast(){
    dist.assign(N + 1, 0);
    
    //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, cst] : G[node]){
            if(dist[node] + cst < dist[next]){
                dist[next] = dist[node] + cst;
                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, next_cst] : 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;
}