Cod sursa(job #2659168)

Utilizator nicu_ducalNicu Ducal nicu_ducal Data 15 octombrie 2020 23:15:50
Problema Flux maxim de cost minim Scor 70
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.05 kb
#include <bits/stdc++.h>
using namespace std;

#define debug(x) cerr << #x << " = " << x << "\n"
#define all(x) (x).begin(),(x).end()
#define len(x) (x).length()
#define sqr(x) (x) * (x)

using ull = unsigned long long;
using ll = long long;
using pii = pair<int, int>;
using pll = pair<ll, ll>;

template <typename T>
ostream& operator<<(ostream &os, const vector<T> &v) { os << '{'; string sep; for (const auto &x : v) os << sep << x, sep = ", "; return os << '}'; }
template <typename A, typename B>
ostream& operator<<(ostream &os, const pair<A, B> &p) { return os << '(' << p.first << ", " << p.second << ')'; }

const int INF = INT_MAX;
const int MOD = 1e9 + 7;
const double EPS = 1e-9;
const double PI = acos(-1);

ll t, n;

struct Graph {
    vector<vector<ll>> adj, capacity, cost;
    vector<ll> parent, dist, new_dist, d;
    ll FlowCost = 0, Flow = 0;

    Graph(int n = -1) {
        init(n);
    }

    void init(int n) {
        adj.resize(n + 1);
        capacity.resize(n + 1, vector<ll>(n + 1, 0));
        cost.resize(n + 1, vector<ll>(n + 1, 0));
        parent.resize(n + 1);
        dist.resize(n + 1, INF);
        new_dist.resize(n + 1, 0);
        d.resize(n + 1, INF);
    }

    void addEdge(ll u, ll v, ll cap, ll _cost) {
        adj[u].push_back(v);
        adj[v].push_back(u);
        capacity[u][v] = cap;
        cost[u][v] = _cost;
        cost[v][u] = -_cost;
    }

    void bellmanFord(ll s) {
        queue<ll> q;
        vector<bool> inQueue(n + 1, false);
        q.push(s);
        inQueue[s] = true;
        dist[s] = 0;
        while (not q.empty()) {
            ll cur = q.front();
            q.pop();
            inQueue[cur] = false;
            for (auto next: adj[cur]) {
                if (capacity[cur][next] and dist[cur] + cost[cur][next] < dist[next]) {
                    dist[next] = dist[cur] + cost[cur][next];
                    if (not inQueue[next]) {
                        q.push(next);
                        inQueue[next] = true;
                    }
                }
            }
        }
    }

    bool dijkstra(ll s, ll t) {
        priority_queue<pll, vector<pll>, greater<pll>> pq;
        pq.push({0, s});
        fill(all(d), INF);
        d[s] = 0, new_dist[s] = 0;
        while (not pq.empty()) {
            ll cur_cost = pq.top().first, cur = pq.top().second;
            pq.pop();
            if (d[cur] != cur_cost) continue;
            for (auto next: adj[cur]) {
                if (capacity[cur][next]) {
                    ll new_d = d[cur] + cost[cur][next] + dist[cur] - dist[next];
                    if (new_d < d[next]) {
                        d[next] = new_d;
                        new_dist[next] = new_dist[cur] + cost[cur][next];
                        parent[next] = cur;
                        pq.push({d[next], next});
                    }
                }
            }
        }
        dist.assign(all(new_dist));
        if (d[t] == INF) return false;
        ll newFlow = INF, newCost = 0, cur = t;
        while (cur != s) {
            newFlow = min(newFlow, capacity[parent[cur]][cur]);
            newCost += cost[parent[cur]][cur];
            cur = parent[cur];
        }
        cur = t;
        while (cur != s) {
            capacity[parent[cur]][cur] -= newFlow;
            capacity[cur][parent[cur]] += newFlow;
            cur = parent[cur];
        }
        Flow += newFlow;
        FlowCost += newFlow * newCost;
        return true;
    }

    ll flow(ll s, ll t) {
        bellmanFord(s);
        while(dijkstra(s, t));
        return FlowCost;
    }
};

int main(){
    ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    /// mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
    ifstream cin("fmcm.in");
    ofstream cout("fmcm.out");

    ll m, s, t, u, v, cap, cost;
    cin >> n >> m >> s >> t;
    Graph g(n);
    for (int i = 1; i <= m; i++) {
        cin >> u >> v >> cap >> cost;
        g.addEdge(u, v, cap, cost);
    }

    cout << g.flow(s, t);

    return 0;
}