Cod sursa(job #3251347)

Utilizator not_anduAndu Scheusan not_andu Data 25 octombrie 2024 19:38:24
Problema Flux maxim de cost minim Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.95 kb
#include <bits/stdc++.h>

using namespace std;

#define INFILE "fmcm.in"
#define OUTFILE "fmcm.out"

const int N_MAX = 350;
const int INF = 1e9;

struct Node {
public:
    int node;
    int cost;

    Node(){}
    Node(int _node, int _cost) : node(_node), cost(_cost) {}

    bool operator<(const Node &other) const {
        return (this -> cost > other.cost);
    }

};

int n, m;
int cost;
int sursa, destinatie;
int parent[N_MAX + 5];
bool inQueue[N_MAX + 5];
int oldDistance[N_MAX + 5];
int realDistance[N_MAX + 5];
int posDistance[N_MAX + 5];
vector<Node> adj[N_MAX + 5];
int capacity[N_MAX + 5][N_MAX + 5];

void bellmanFord(){

    memset(oldDistance, 0x3f3f3f3f, sizeof oldDistance);
    oldDistance[sursa] = 0;
    inQueue[sursa] = true;

    queue<int> q; q.push(sursa);

    while(!q.empty()){
        int node = q.front(); q.pop();
        inQueue[node] = false;
        for(auto &to : adj[node]){
            if(capacity[node][to.node] && oldDistance[node] + to.cost < oldDistance[to.node]){
                oldDistance[to.node] = oldDistance[node] + to.cost;
                if(!inQueue[to.node]){
                    q.push(to.node);
                    inQueue[to.node] = true;
                }
            }
        }
    }

}

bool dijkstra(){

    memset(posDistance, 0x3f3f3f3f, sizeof posDistance);
    posDistance[sursa] = 0;
    realDistance[sursa] = 0;

    priority_queue<Node> q; q.push(Node(sursa, 0));
    while(!q.empty()){

        int node = q.top().node;
        int cost = q.top().cost;
        q.pop();

        if(posDistance[node] != cost) continue;

        for(auto &to : adj[node]){

            int auxCost = posDistance[node] + to.cost + oldDistance[node] - oldDistance[to.node];
            if(capacity[node][to.node] && auxCost < posDistance[to.node]){
                posDistance[to.node] = auxCost;
                realDistance[to.node] = realDistance[node] + to.cost;
                parent[to.node] = node;
                q.push(Node(to.node, auxCost));
            }

        }

    }

    memcpy(oldDistance, realDistance, sizeof realDistance);

    return (posDistance[destinatie] < INF);

}

void solve(){

    cin >> n >> m >> sursa >> destinatie;

    for(int i = 0; i < m; ++i){
        int node, to, cap, cost; cin >> node >> to >> cap >> cost;
        adj[node].push_back(Node(to, cost));
        adj[to].push_back(Node(node, -cost));
        capacity[node][to] = cap;
    }

    bellmanFord();

    while(dijkstra()){
        int flow = INF;
        for(int i = destinatie; i != sursa; i = parent[i]) flow = min(flow, capacity[parent[i]][i]);
        for(int i = destinatie; i != sursa; i = parent[i]){
            capacity[parent[i]][i] -= flow;
            capacity[i][parent[i]] += flow;
        }
        cost += flow * realDistance[destinatie];
    }

    cout << cost << '\n';

}

int main(){
    ios_base::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    freopen(INFILE, "r", stdin);
    freopen(OUTFILE, "w", stdout);
    solve();
    return 0;
}