Cod sursa(job #2884183)

Utilizator alex_braslasuBraslasu Alexandru alex_braslasu Data 2 aprilie 2022 15:47:46
Problema Flux maxim de cost minim Scor 70
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.39 kb
#include <fstream>
#include <vector>
#include <queue>

using namespace std;

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

const int INF = (1LL << 31) - 1;
int n, m, S, D, x, y, z, t, i, TOTAL, flux, mini, costmin, lg_heap, T[360], c[360][360], cost[360][360], f[360][360], drum[360], heap[360];
vector<int > G[360];
queue<int > q;
bool ok[360];

static inline void UpHeap(int nod)
{
    int tata = nod / 2;
    if (tata && drum[heap[tata]] > drum[heap[nod]])
    {
        swap(heap[nod], heap[tata]);
        UpHeap(tata);
    }
}

static inline void DownHeap(int nod)
{
    int fiu = 2 * nod;
    if (fiu <= lg_heap && fiu + 1 <= n && drum[heap[fiu + 1]] < drum[heap[fiu]])
        ++fiu;
    if (fiu <= lg_heap && drum[heap[nod]] > drum[heap[fiu]])
    {
        swap(heap[nod], heap[fiu]);
        DownHeap(fiu);
    }
}

static inline void Insert(int x)
{
    heap[++lg_heap] = x;
    UpHeap(lg_heap);
}

static inline void Delete()
{
    swap(heap[1], heap[lg_heap]);
    --lg_heap;
    DownHeap(1);
}

static inline void Bellman()
{
    for (int i = 1; i <= n; ++i)
        drum[i] = INF, ok[i] = false;
    drum[S] = 0;
    ok[S] = true;
    q.push(S);
    while (!q.empty())
    {
        int nod = q.front();
        ok[nod] = false;
        q.pop();
        for (auto it : G[nod])
            if (c[nod][it] > f[nod][it] && drum[nod] + cost[nod][it] < drum[it])
            {
                drum[it] = drum[nod] + cost[nod][it];
                if (!ok[it])
                {
                    q.push(it);
                    ok[it] = true;
                }
            }
    }
    TOTAL = drum[D];
}

static inline int Dijkstra()
{
    for (int i = 1; i <= n; ++i)
        if (drum[i] != INF)
            for (auto it : G[i])
                if (drum[it] != INF)
                    cost[i][it] += drum[i] - drum[it];
    for (int i = 1; i <= n; ++i)
        drum[i] = INF, ok[i] = false;
    drum[S] = 0;
    Insert(S);
    ok[S] = true;
    while (lg_heap)
    {
        int nod = heap[1];
        Delete();
        ok[nod] = false;
        for (auto it : G[nod])
            if (c[nod][it] > f[nod][it] && drum[nod] + cost[nod][it] < drum[it])
            {
                drum[it] = drum[nod] + cost[nod][it];
                T[it] = nod;
                if (!ok[it])
                {
                    Insert(it);
                    ok[it] = true;
                }
            }
    }
    if (drum[D] != INF)
        return 1;
    return 0;
}

int main()
{
    ios::sync_with_stdio(false);
    fin.tie(nullptr);
    fin >> n >> m >> S >> D;
    for (i = 1; i <= m; ++i)
    {
        fin >> x >> y >> z >> t;
        G[x].push_back(y);
        G[y].push_back(x);
        c[x][y] = z;
        cost[x][y] = t;
        cost[y][x] = -t;
    }
    Bellman();
    while (Dijkstra())
    {
        mini = 0;
        flux = INF;
        int nod = D;
        while (nod != S)
        {
            if (c[T[nod]][nod] - f[T[nod]][nod] < flux)
                flux = c[T[nod]][nod] - f[T[nod]][nod];
            nod = T[nod];
        }
        nod = D;
        while (nod != S)
        {
            f[T[nod]][nod] += flux;
            f[nod][T[nod]] -= flux;
            nod = T[nod];
        }
        TOTAL += drum[D];
        costmin += flux * TOTAL;
    }
    fout << costmin;
    return 0;
}