Cod sursa(job #3220425)

Utilizator tibinyteCozma Tiberiu-Stefan tibinyte Data 3 aprilie 2024 16:12:12
Problema Flux maxim de cost minim Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.08 kb
#include <bits/stdc++.h>

#define int long long

using namespace std;

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

int random(int st, int dr)
{
    uniform_int_distribution<int> dist(st, dr);
    return dist(rng);
}

#define cin fin
#define cout fout

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

const int inf = 1e13;

struct edge
{
    int u, v, cap, flow, cost;
};

struct MCMF
{
    vector<edge> edg;
    vector<vector<int>> g;
    vector<int> potential;
    int n;
    int s, t;
    MCMF(int n, int s, int t) : n(n), s(s), t(t)
    {
        g.resize(n + 1);
        potential.resize(n + 1);
    }
    void add_edge(int u, int v, int c, int cost)
    {
        int sz = edg.size();
        edg.push_back({u, v, c, 0, cost});
        edg.push_back({v, u, 0, 0, -cost});
        g[u].push_back(sz);
        g[v].push_back(sz + 1);
    }

    void bellman()
    {
        fill(potential.begin(), potential.end(), inf);
        potential[s] = 0;
        bool wtf = false;
        for (int i = 1; i <= n; ++i)
        {
            for (int x = 0; x < edg.size(); ++x)
            {
                auto j = edg[x];
                if (j.cap - j.flow > 0)
                {
                    potential[j.v] = min(potential[j.v], potential[j.u] + j.cost);
                }
            }
        }
    }

    pair<int, int> dijkstra()
    {
        vector<int> dist(n + 1, inf);
        dist[s] = 0;

        vector<int> par(n + 1);

        priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> best;
        best.push({0, s});

        vector<bool> vis(n + 1);

        while (!best.empty())
        {
            auto [cost, qui] = best.top();
            best.pop();
            if (vis[qui])
            {
                continue;
            }
            vis[qui] = true;

            for (auto i : g[qui])
            {
                auto e = edg[i];
                if (e.cap - e.flow == 0)
                {
                    continue;
                }

                int lying = e.cost + potential[e.u] - potential[e.v];

                if (cost + lying < dist[e.v])
                {
                    dist[e.v] = cost + lying;
                    par[e.v] = i;
                    best.push({dist[e.v], e.v});
                }
            }
        }

        if (dist[t] == inf)
        {
            return {0, inf};
        }

        for (int i = 1; i <= n; ++i)
        {
            if (dist[i] == inf)
            {
                potential[i] = random(0, 1e9);
            }
            else
            {
                potential[i] += dist[i];
            }
        }

        pair<int, int> ans;
        int push = inf;
        int frog = t;
        while (frog != s)
        {
            int cap = edg[par[frog]].cap - edg[par[frog]].flow;
            push = min(push, cap);
            frog = edg[par[frog]].u;
        }
        frog = t;
        ans.first = push;

        int c = potential[s] - potential[t];

        while (frog != s)
        {
            int x = par[frog];
            edg[x].flow += push;
            edg[x ^ 1].flow -= push;
            ans.second += (edg[x].cost + potential[edg[x].u] - potential[edg[x].v]) * push;
            frog = edg[x].u;
        }
        ans.second -= c * push;
        return ans;
    }

    pair<int, int> flow()
    {
        bellman();
        pair<int, int> ans;
        while (true)
        {
            pair<int, int> add = dijkstra();
            if (add.first == 0)
            {
                return ans;
            }
            ans.first += add.first;
            ans.second += add.second;
        }
    }
};
int32_t main()
{
    cin.tie(nullptr)->sync_with_stdio(false);
    int n, m, s, d;
    cin >> n >> m >> s >> d;
    MCMF G(n, s, d);
    for (int i = 1; i <= m; ++i)
    {
        int a, b, cap, cost;
        cin >> a >> b >> cap >> cost;
        G.add_edge(a, b, cap, cost);
    }
    cout << G.flow().second << '\n';
}