Cod sursa(job #3222511)

Utilizator alexdumitruAlexandru Dumitru alexdumitru Data 10 aprilie 2024 16:25:48
Problema Flux maxim de cost minim Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.35 kb
#include <bits/stdc++.h>

using namespace std;
using ll = long long;

ifstream fin("fmcm.in");
ofstream fout("fmcm.out");

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

struct edge {
    int to, cap, flow, cost, rid;
};

int n, m, s, t;
vector<edge> g[NMAX + 1];
int dist[NMAX + 1];
ll costDist[NMAX + 1];
int potential[NMAX + 1];
bool inQueue[NMAX + 1];
bool vis[NMAX + 1];
int ptrToParent[NMAX + 1];
int flow[NMAX + 1];

void add_edge(int u, int v, int c, int z) {
    int r1 = g[v].size();
    int r2 = g[u].size();
    g[u].push_back({v, c, 0, z, r1});
    g[v].push_back({u, 0, 0, -z, r2});
}

void compute_potentials(int s) {
    //run bellman ford to calculate the distances
    //set potential equal to the distances
    for (int i = 1; i <= n; i++)
        potential[i] = INF;
    queue<int> q;
    q.push(s);
    potential[s] = 0;
    while (!q.empty()) {
        int node = q.front();
        q.pop();
        inQueue[node] = false;
        for (auto &it : g[node]) {
            if (it.cap <= it.flow) continue; //ignore edges from residual graph
            if (potential[node] + it.cost < potential[it.to]) {
                potential[it.to] = potential[node] + it.cost;
                if (!inQueue[it.to]) {
                    inQueue[it.to] = true;
                    q.push(it.to);
                }
            }
        }
    }
}

int dijkstra(int s, int t) {
    for (int i = 1; i <= n; i++) {
        dist[i] = INF;
        flow[i] = 0;
        vis[i] = 0;
        ptrToParent[i] = 0;
    }
    dist[s] = 0;
    flow[s] = INF;
    //heap (dist, node)
    priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;
    pq.push(make_pair(0, s));
    while (!pq.empty()) {
        int node = pq.top().second;
        pq.pop();
        if (vis[node]) continue;
        vis[node] = 1;

        for (auto &it : g[node]) {
            if (it.flow < it.cap && 1 && dist[it.to] > dist[node] - potential[it.to] + potential[node] + it.cost) {
                dist[it.to] = dist[node] - potential[it.to] + potential[node] + it.cost;
                flow[it.to] = min(flow[node], it.cap - it.flow);
                ptrToParent[it.to] = it.rid;
                pq.push(make_pair(dist[it.to], it.to));
            }
        }
    }
    //return the new flow
    return flow[t];
}

pair<int, ll> min_cost_max_flow(int s, int t) {
    int flow = 0, newFlow = 0;
    ll cost = 0;
    while (newFlow = dijkstra(s, t)) {
        for (int i = 1; i <= n; i++)
            dist[i] += potential[i] - potential[s];
        for (int i = 1; i <= n; i++)
            potential[i] = dist[i];
        flow += newFlow;
        cost += 1LL * newFlow * dist[t];
        int node = t;
        while (node != s) {
            g[node][ptrToParent[node]].flow -= newFlow;
            g[g[node][ptrToParent[node]].to][g[node][ptrToParent[node]].rid].flow += newFlow;
            node = g[node][ptrToParent[node]].to;
        }
    }
    return make_pair(flow, cost);
}

void read() {
    fin >> n >> m >> s >> t;
    for (int i = 1; i <= m; i++) {
        int u, v, c, z;
        fin >> u >> v >> c >> z;
        add_edge(u, v, c, z);
    }
}

void solve() {
    compute_potentials(s);
    fout << min_cost_max_flow(s, t).second << '\n';
}

int main() {
    read();
    solve();
    return 0;
}