Cod sursa(job #2164752)

Utilizator marcdariaDaria Marc marcdaria Data 13 martie 2018 09:37:29
Problema Flux maxim de cost minim Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.92 kb
#include <fstream>
#include <vector>
#include <bitset>
#include <queue>

using namespace std;

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

struct Node
{
    int nod, cost;

    const bool operator< (const Node &other) const
    {
        return cost > other.cost;
    }
};

const int NMAX = 351;

int n, m, source, sink;
int cap[NMAX][NMAX], cst[NMAX][NMAX];
vector<vector<int> > v;
int flw, minCostFlw;

int oldD[NMAX];
bitset<NMAX> inQueue;

int d[NMAX], realD[NMAX], t[NMAX];
priority_queue<Node> pq;

void Read()
{
    fin >> n >> m >> source >> sink;
    int x, y;
    v = vector<vector<int> >(n + 1);

    while (m--)
        {
        fin >> x >> y;
        v[x].push_back(y);
        v[y].push_back(x);
        fin >> cap[x][y] >> cst[x][y];
        cst[y][x] = -cst[x][y];
    }
}

void BellmanFord()
{
    for (int i = 1; i <= n; ++i)
        oldD[i] = 0x3f3f3f3f;
    oldD[source] = 0;
    queue<int> q;

    int node;
    for (q.push(source), inQueue[source] = 1; q.size(); q.pop())
        {
        node = q.front();
        inQueue[node] = 0;

        for (const int& other: v[node])
            {
            if (cap[node][other])
            {
                if (oldD[node] + cst[node][other] >= oldD[other])
                    continue;
                oldD[other] = oldD[node] + cst[node][other];
                if (inQueue[other])
                    continue;

                inQueue[other] = 1;
                q.push(other);
            }
        }
    }
}

bool Dijkstra()
{
    for (int i = 1; i <= n; ++i)
        d[i] = 0x3f3f3f3f;
    d[source] = 0;
    realD[source] = 0;
    pq.push({source, d[source]});

    int x, dx;
    int newD;
    while (pq.size())
        {
        x = pq.top().nod, dx = pq.top().cost;
        pq.pop();
        if (d[x] != dx)
            continue;

        for (const int& y: v[x])
            {
            if (cap[x][y])
            {
                newD = d[x] + cst[x][y] + oldD[x] - oldD[y];
                if (newD < d[y]) {
                    d[y] = newD;
                    realD[y] = realD[x] + cst[x][y];
                    t[y] = x;
                    pq.push({y, d[y]});
                }
            }
        }
    }

    for (int i = 1; i <= n; ++i)
        oldD[i] = realD[i];

    if (d[sink] == 0x3f3f3f3f)
        return false;
    int mn = 0x3f3f3f3f, currCost = 0;
    for (int i = sink; i != source; i = t[i])
        {
            mn = min(mn, cap[t[i]][i]);
            currCost += cst[t[i]][i];
        }

    flw += mn;
    minCostFlw += mn * realD[sink];
    for (int i = sink; i != source; i = t[i])
        {
            cap[t[i]][i] -= mn;
            cap[i][t[i]] += mn;
        }
    return 1;
}

int main()
{
    Read();
    BellmanFord();
    while (Dijkstra());
    fout << minCostFlw;

    fin.close();
    fout.close();
    return 0;
}