Cod sursa(job #2962718)

Utilizator witekIani Ispas witek Data 8 ianuarie 2023 23:23:12
Problema Flux maxim de cost minim Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.2 kb
#include <fstream>
#include <iostream>
#include <vector>
#include <queue>

using namespace std;

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

struct Edge {
    int nod, cost;

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

const int oo = 1e9;
int n, m, source, dest;
vector <vector <int>> cap, cst;
vector<vector<int> > v;
vector <int> oldDistances, realDistances;
int minCostFlow, flow;

void init() {
    cap = vector <vector<int>> (n + 1, vector <int> (n + 1));
    cst = vector <vector<int>> (n + 1, vector <int> (n + 1));
    v = vector <vector <int>> (n + 1);
    oldDistances = vector <int> (n + 1, oo);
    realDistances = vector <int> (n + 1, oo);
}

void read() {
    fin >> n >> m >> source >> dest;
    init();
    int x, y, capacity, cost;
    for (int i = 1; i <= m; ++i) {
        fin >> x >> y >> capacity >> cost;
        v[x].push_back(y);
        v[y].push_back(x);
        cap[x][y] = capacity;
        cst[x][y] = cost;
        cst[y][x] = -cost;
    }
}

void bellmanFord() {
    queue <int> q;
    vector <bool> inQueue(n + 1);
    oldDistances[source] = 0;
    q.push(source);

    while (!q.empty()) {
        int node = q.front();
        q.pop();
        inQueue[node] = false;
        for (auto neighbor: v[node]) {
            if (cap[node][neighbor]) {
                if (oldDistances[node] + cst[node][neighbor] < oldDistances[neighbor]) {
                    oldDistances[neighbor] = oldDistances[node] + cst[node][neighbor];

                    if (!inQueue[neighbor]) {
                        q.push(neighbor);
                        inQueue[neighbor] = true;
                    }
                }
            }
        }
    }
}

bool dijkstra() {
    vector <int> d(n + 1, oo);
    vector <int> t(n + 1);
    priority_queue<Edge> pq;
    d[source] = 0;
    realDistances[source] = 0;
    pq.push({source, 0});


    int node, dist, otherDist;
    while(!pq.empty()) {
        node = pq.top().nod;
        dist = pq.top().cost;
        pq.pop();
        if(d[node] != dist)
            continue;
        for(const auto& neighbor : v[node]) {
            if(cap[node][neighbor]) {
                otherDist = d[node] + cst[node][neighbor] + oldDistances[node] - oldDistances[neighbor];
                if(otherDist < d[neighbor]) {
                    d[neighbor] = otherDist;
                    realDistances[neighbor] = realDistances[node] + cst[node][neighbor];
                    t[neighbor] = node;
                    pq.push({neighbor, d[neighbor]});
                }

            }
        }
    }

    if(d[dest] == oo)
        return false;

    int path_capacity = 1e9, path_price = 0;

    for (int node = dest; node != source; node = t[node]) {
        if (cap[t[node]][node] < path_capacity)
            path_capacity = cap[t[node]][node];
        path_price += cst[t[node]][node];
    }

    flow += path_capacity;
    minCostFlow += path_capacity * realDistances[dest];

    for (int node = dest; node != source; node = t[node]) {
        cap[t[node]][node] -= path_capacity;
        cap[node][t[node]] += path_capacity;
    }
    return true;
}

int main()
{
    read();
    bellmanFord();
    while (dijkstra());
    fout << minCostFlow;
    return 0;
}