Cod sursa(job #3200290)

Utilizator RobertAcAcatrinei Robert-Marian RobertAc Data 4 februarie 2024 11:22:03
Problema Flux maxim de cost minim Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.45 kb
#include <bits/stdc++.h>
#ifdef LOCAL
#define in cin
#define out cout
#endif

using namespace std;

#ifndef LOCAL
ifstream in("fmcm.in");
ofstream out("fmcm.out");
#endif

const int mmax = 12505;
const int nmax = 355;
const int inf = 1e9;
int n, m, s, d;

bool viz[nmax];
int dist[nmax];
int entered[nmax];

int pi[nmax];

struct edge
{
    int fr, nxt, c, w;
    edge(int fr = 0, int nxt = 0, int c = 0, int w = 0) : fr(fr), nxt(nxt), c(c), w(w) {}
    void debug()
    {
        cerr << fr << ' ' << nxt << ' ' << c << ' ' << w << '\n';
    }
} edges[2 * mmax];

vector<int> adj[nmax];

void resetDist()
{
    for (int i = 1; i <= n; i++)
    {
        dist[i] = inf;
        viz[i] = 0;
    }
}

void topi()
{
    // cerr << "pis\n";
    for (int i = 1; i <= n; i++)
    {
        // cerr << i << '\n';
        // cerr << pi[i] << ' ';
        pi[i] += dist[i];
        // cerr << pi[i] << '\n';
    }
}

struct dijelem
{
    int a, b;
    dijelem(int a, int b) : a(a), b(b) {}
    bool operator<(const dijelem &other) const
    {
        b > other.b;
    }
};

int trans(int a, int b, int w)
{
    return a - b + w;
}

bool dijkstra()
{
    resetDist();
    priority_queue<dijelem> pq;
    pq.push({s, 0});
    dist[s] = 0;
    while (!pq.empty())
    {
        int nod = pq.top().a;
        pq.pop();
        if (viz[nod])
            continue;
        viz[nod] = 1;
        for (auto i : adj[nod])
        {
            if (edges[i].c != 0)
            {
                int tmp = trans(pi[nod], pi[edges[i].nxt], edges[i].w);
                if (dist[edges[i].nxt] > dist[nod] + tmp)
                {
                    entered[edges[i].nxt] = i;
                    dist[edges[i].nxt] = dist[nod] + tmp;
                    pq.push({edges[i].nxt, dist[edges[i].nxt]});
                }
            }
        }
    }
    if (dist[d] == inf)
        return 0;
    topi();
    return 1;
}

void bellmanford()
{
    queue<int> q;
    dist[s] = 0;
    q.push(s);
    viz[s] = 1;
    while (!q.empty())
    {
        int nod = q.front();
        q.pop();
        viz[nod] = 0;
        for (auto i : adj[nod])
        {
            if (edges[i].c == 0)
                continue;
            if (dist[edges[i].nxt] > dist[nod] + edges[i].w)
            {
                dist[edges[i].nxt] = dist[nod] + edges[i].w;
                if (!viz[edges[i].nxt])
                {
                    viz[edges[i].nxt] = 1;
                    q.push(edges[i].nxt);
                }
            }
        }
    }
    topi();
}

void bkt1(int nod, int &cst, int &flux)
{
    if (nod == s)
        return;
    cst += edges[entered[nod]].w;
    flux = min(flux, edges[entered[nod]].c);
    bkt1(edges[entered[nod]].fr, cst, flux);
}

void bkt2(int nod, int &cst, int &flux)
{
    if (nod == s)
        return;
    edges[entered[nod]].c -= flux;
    edges[entered[nod] ^ 1].c += flux;
    bkt2(edges[entered[nod]].fr, cst, flux);
}

int main()
{
    in >> n >> m >> s >> d;
    for (int i = 0, ind = 0; i < m; i++, ind += 2)
    {
        int a, b, c, w;
        in >> a >> b >> c >> w;
        edges[ind] = edge(a, b, c, w);
        edges[ind + 1] = edge(b, a, 0, -w);
        adj[a].push_back(ind);
        adj[b].push_back(ind + 1);
    }
    resetDist();
    bellmanford();
    int tot = 0;
    while (dijkstra())
    {
        int cst = 0, flux = inf;
        bkt1(d, cst, flux);
        bkt2(d, cst, flux);
        tot += cst * flux;
        /*
            1 -6
            3 -4
            8 -3
        */
    }
    out << tot;
}