Cod sursa(job #3351264)

Utilizator toma_ariciuAriciu Toma toma_ariciu Data 18 aprilie 2026 11:14:26
Problema Flux maxim de cost minim Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.65 kb
/// ma cred smecher
#include <bits/stdc++.h>

using namespace std;
using ll = long long;
#define int ll

const int maxN = 100005, inf = 1e9;

struct FlowGraph {
    int n, s, d;
    struct Edge {
        int nxt, flow, cap, cost;
    };
    vector <Edge> edgeList;
    vector <vector <int>> G;
    vector <int> potential, prv;

    void addEdge(int x, int y, int cap, int cost) {
        G[x].push_back(edgeList.size());
        edgeList.push_back({y, 0, cap, cost});

        G[y].push_back(edgeList.size());
        edgeList.push_back({x, 0, 0, -cost});
    }

    void bellmanFord() {
        for (int i = 0; i < n; i++) {
            potential[i] = inf;
        }
        queue <int> q;
        vector <int> inQ(n);

        q.push(s);
        potential[s] = 0;
        inQ[s] = 1;

        while (!q.empty()) {
            int nod = q.front();
            q.pop();
            inQ[nod] = 0;

            for (int idx : G[nod]) {
                auto [nxt, flux, cap, cost] = edgeList[idx];
                if (flux == cap) {
                    continue;
                }

                if (potential[nod] + cost < potential[nxt]) {
                    potential[nxt] = potential[nod] + cost;
                    if (!inQ[nxt]) {
                        q.push(nxt);
                        inQ[nxt] = 1;
                    }
                }
            }
        }
    }

    bool dijkstra() {
        vector <int> dist(n, inf);
        vector <int> newPot(n, inf);
        
        priority_queue <pair <int, int>> heap;
        heap.push({0, s});
        dist[s] = 0;
        newPot[s] = 0;

        while (!heap.empty()) {
            auto [d, nod] = heap.top();
            heap.pop();
            d = -d;
            if (dist[nod] != d) {
                continue;
            }

            for (int idx : G[nod]) {
                auto [nxt, flux, cap, cost] = edgeList[idx];
                if (flux == cap) {
                    continue;
                }

                if (dist[nod] + cost + potential[nod] - potential[nxt] < dist[nxt]) {
                    dist[nxt] = dist[nod] + cost + potential[nod] - potential[nxt];
                    newPot[nxt] = newPot[nod] + cost;
                    prv[nxt] = idx;

                    heap.push({-dist[nxt], nxt});
                }
            }
        }

        potential = newPot;

        return dist[d] != inf;
    }

    int getCost() {
        int cost = 0;
        bellmanFord();

        while (dijkstra()) {
            int flow = inf;
            for (int nod = d; nod != s; nod = edgeList[prv[nod] ^ 1].nxt) {
                flow = min(flow, edgeList[prv[nod]].cap - edgeList[prv[nod]].flow);
            }

            for (int nod = d; nod != s; nod = edgeList[prv[nod] ^ 1].nxt) {
                edgeList[prv[nod]].flow += flow;
                edgeList[prv[nod] ^ 1].flow -= flow;
            }

            cost += flow * potential[d];
        }

        return cost;
    }

    FlowGraph(int n_) : n(n_), G(n), potential(n), prv(n) {}
};

void solve() {
    int n, m, s, d;
    cin >> n >> m >> s >> d;

    FlowGraph graph(n);
    graph.s = s - 1;
    graph.d = d - 1;

    for (int i = 0; i < m; i++) {
        int x, y, c, z;
        cin >> x >> y >> c >> z;
        x--, y--;
        graph.addEdge(x, y, c, z);
    }

    cout << graph.getCost();
}

void prec() {

}

signed main() {
#ifdef LOCAL
    freopen("test.in", "r", stdin);
    freopen("test.out", "w", stdout);
#else
    freopen("fmcm.in", "r", stdin);
    freopen("fmcm.out", "w", stdout);
#endif
    ios_base::sync_with_stdio(false);
    cin.tie(0);

    prec();

    int nrt = 1;
    // cin >> nrt;

    for (int t = 1; t <= nrt; t++) {
        solve();
    }

    return 0;
}