Cod sursa(job #1962856)

Utilizator razvan242Zoltan Razvan-Daniel razvan242 Data 12 aprilie 2017 09:09:11
Problema Flux maxim de cost minim Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.82 kb
#include <fstream>
#include <vector>
#include <bitset>
#include <queue>

using namespace std;

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

struct Pair {
    int nod, cost;

    const bool operator< (const Pair &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<Pair> pq;

inline 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];
    }
}

inline 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);
            }
        }
    }
}

inline 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;
}