Cod sursa(job #2965706)

Utilizator user12345user user user user12345 Data 15 ianuarie 2023 21:49:55
Problema Flux maxim de cost minim Scor 20
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.23 kb
#include <bits/stdc++.h> 
using namespace std;

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

template <class obj> 
class heap {
private:

    struct nod {
        obj val;
        nod* down, * next;

        nod(obj val)
        {
            this->val = val;
            down = next = NULL;
        }
    };

    nod* root;

    inline nod* unit(nod* a, nod* b)
    {
        if (a == NULL)
            return b;

        if (b == NULL)
            return a;

        if (!(a->val < b->val))
            swap(a, b);

        b->next = a->down;
        a->down = b;

        return a;
    }

    nod* convert(nod* x)
    {
        if (x == NULL || x->next == NULL)
            return x;

        nod* next1 = x->next;
        nod* next2 = next1->next;

        return unit(unit(x, next1), convert(next2));
    }

public:

    inline heap()
    {
        root = NULL;
    }

    inline void add(obj val)
    {
        root = unit(root, new nod(val));
    }

    inline obj top()
    {
        return root->val;
    }

    inline bool empty()
    {
        return root == NULL;
    }

    inline void pop()
    {
        root = convert(root->down);
    }

    inline void clear()
    {
        root = NULL;
    }
};

int d[351];

struct nod {
    int x, flow, costTotal, costSum;

    bool operator < (nod& aux)
    {
        return d[x] < d[aux.x] || (d[x] == d[aux.x] && flow > aux.flow);
    }
};

heap <nod> H;
int src, dest, flow[351][351], cost[351][351], n, m;
int t[351];
int bound, maxi;
vector <int> g[351];
const int inf = 1000000000;

inline bool bfs()
{
    H.clear();

    for (int i = 1; i <= n; i++)
        d[i] = inf;

    d[src] = 0;
    H.add({ src, inf, 0, 0});
    maxi = 0;

    while (!H.empty())
    {
        nod x = H.top();
        H.pop();

        if (d[x.x] != x.costTotal)
            continue;

        if (x.x == dest)
        {
            maxi = x.flow;
            break;
        }

        for (auto& i : g[x.x])
        {
            if (!flow[x.x][i] || d[i] < d[x.x] + (x.costSum + cost[x.x][i] + bound) * min(x.flow, flow[x.x][i]))
                continue;

            d[i] = d[x.x] + (x.costSum + cost[x.x][i] + bound) * min(x.flow, flow[x.x][i]);
            H.add({ i, min(x.flow, flow[x.x][i]), d[i], x.costTotal + cost[x.x][i] + bound});
            t[i] = x.x;
        }
    }

    return maxi;
}

int maxFlow()
{
    int res = 0;

    while (bfs())
    {
        int a, b;
        b = dest;
        a = t[dest];

        while (b != src)
        {
            flow[a][b] -= maxi;
            flow[b][a] += maxi;
            res += cost[a][b] * maxi;

            b = a;
            a = t[a];
        }
    }

    return res;
}

int main()
{
    fin >> n >> m >> src >> dest;

    for (int i = 1; i <= m; i++)
    {
        int x, y, cap, cst;
        fin >> x >> y >> cap >> cst;

        g[x].push_back(y);
        g[y].push_back(x);

        flow[x][y] = cap;
        cost[x][y] = cost[y][x] = cst;

        bound = min(bound, cst);
    }

    if (bound < 0)
        bound = -bound + 1;
    else
        bound = 0;

    fout << maxFlow();

    return 0;
}