Cod sursa(job #2416443)

Utilizator akaprosAna Kapros akapros Data 27 aprilie 2019 16:08:56
Problema Flux maxim de cost minim Scor 50
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.63 kb
#include <bits/stdc++.h>
#define maxN 352

#define inf 0x3fffffff

using namespace std;

FILE *fin = freopen("fmcm.in", "r", stdin);
FILE *fout = freopen("fmcm.out", "w", stdout);

int n, m;
int S, D;

vector < int > V[maxN];
int Cost[maxN][maxN], R[maxN][maxN];
int par[maxN];


int old_d[maxN], real_d[maxN], d[maxN];
struct Pq
{
    int x, y;
    bool operator < (const Pq &ot) const
    {
        if (y == ot.y)
            return x < ot.x;
        return y < ot.y;
    }
};
priority_queue <Pq> H;
queue < int > Q;

void AddEdge(int u, int v, int cap, int cost)
{
    V[u].push_back(v);
    V[v].push_back(u);
    Cost[u][v] = cost;
    Cost[v][u] = -cost;
    R[u][v] = cap;
}

int ans;

bool Dijkstra()
{
    for (int i = 0; i < n; ++ i)
        real_d[i] = d[i] = inf;
    real_d[S] = d[S] = 0;
    H.push(Pq{S, d[S]});
    while (!H.empty())
    {
        Pq nod = H.top();
        H.pop();
        if (d[nod.x] != nod.y) continue;
        int u = nod.x;
        for (int v : V[u])
            if (R[u][v])
            {
                int newD = d[u] + old_d[u] - old_d[v] + Cost[u][v];
                if (newD < d[v])
                {
                    d[v] = newD;
                    par[v] = u;
                    real_d[v] = real_d[u] + Cost[u][v];
                    H.push(Pq{v, d[v]});
                }
            }
    }
    if (real_d[D] == inf)
        return false;
    int nod = D, crtFlow = inf;
    while (nod != S)
    {
        crtFlow = min(crtFlow, R[par[nod]][nod]);
        nod = par[nod];
    }
    if (!crtFlow) return false;
    nod = D;
    while (nod != S)
    {
        R[par[nod]][nod] -= crtFlow;
        R[nod][par[nod]] += crtFlow;
        nod = par[nod];
    }
    ans += crtFlow * real_d[D];
    memcpy(old_d, real_d, sizeof(real_d));
    return true;
}
void BellmanFord()
{
    Q.push(S);
    for (int i = 0; i < n; ++ i)
        old_d[i] = inf;
    old_d[S] = 0;
    while (!Q.empty())
    {
        int nod = Q.front();
        Q.pop();
        for (int adj : V[nod])
            if (R[nod][adj] && old_d[adj] > old_d[nod] + Cost[nod][adj])
            {
                old_d[adj] = old_d[nod] + Cost[nod][adj];
                Q.push(adj);
            }
    }
}

int main()
{
    scanf("%d%d%d%d", &n, &m, &S, &D);
    -- S;
    -- D;
    for (int i = 0; i < m; ++ i)
    {
        int u, v, cap, cost;
        scanf("%d%d%d%d", &u, &v, &cap, &cost);
        -- u;
        -- v;
        AddEdge(u, v, cap, cost);
    }
    BellmanFord();
    while (Dijkstra());

    printf("%d\n", ans);

    return 0;
}