Pagini recente » Cod sursa (job #3187181) | Cod sursa (job #341662) | Cod sursa (job #530508) | Cod sursa (job #1985478) | Cod sursa (job #1976646)
#include <bits/stdc++.h>
using namespace std;
template <class T, T INF=0x3f3f3f3f>
class MaxFlowMinimalCost {
typedef vector<vector<int>> Graph;
typedef unordered_map<size_t, unordered_map<size_t, T>> SparseMatrix;
T flow_val_;
T cost_val_;
Graph graph_;
SparseMatrix capacity_;
SparseMatrix flow_;
SparseMatrix cost_;
vector<T> read_dist;
public:
MaxFlowMinimalCost(size_t n) {
graph_.resize(n + 1);
}
virtual void add_edge(size_t x, size_t y, T capacity, T cost) {
graph_[x].push_back(y);
graph_[y].push_back(x);
capacity_[x][y] += capacity;
capacity_[y][x] += 0;
cost_[x][y] = cost;
cost_[y][x] = -cost;
}
SparseMatrix get_flow() {
return flow_;
}
vector<T> bellmanFord(int start) {
queue<size_t> q;
vector<size_t> parent(graph_.size(), 0);
vector<T> dist(graph_.size(), INF);
vector<bool> in_queue(graph_.size(), false);
q.push(start);
in_queue[start] = true;
dist[start] = 0;
while (!q.empty()) {
size_t node = q.front(); q.pop();
for (size_t neigh : graph_[node]) {
if (flow_[node][neigh] < capacity_[node][neigh] && dist[node] + cost_[node][neigh] < dist[neigh]) {
dist[neigh] = dist[node] + cost_[node][neigh];
parent[neigh] = node;
if (!in_queue[neigh]) {
in_queue[neigh] = true;
q.push(neigh);
}
}
}
in_queue[node] = false;
}
return dist;
}
vector<size_t> dijkstra(int start, vector<T>& bellman_cost) {
vector<T> dist(graph_.size(), INF);
vector<size_t> parent(graph_.size(), 0);
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> q;
read_dist.resize(graph_.size());
dist[start] = 0;
read_dist[start] = 0;
q.push({dist[start], start});
while (!q.empty()) {
int cost = q.top().first;
int node = q.top().second;
q.pop();
if (dist[node] != cost) {
continue;
}
for (size_t neigh : graph_[node]) {
if (flow_[node][neigh] < capacity_[node][neigh]) {
int new_dist = dist[node] + cost_[node][neigh] + bellman_cost[node] - bellman_cost[neigh];
if (new_dist < dist[neigh]) {
dist[neigh] = new_dist;
read_dist[neigh] = read_dist[node] + cost_[node][neigh];
parent[neigh] = node;
q.push({dist[neigh], neigh});
}
}
}
}
bellman_cost = read_dist;
return parent;
}
pair<T, T> do_flow(size_t start, size_t finish) {
T flow = 0;
T cost = 0;
auto bellman_cost = bellmanFord(start);
while (true) {
auto parent = dijkstra(start, bellman_cost);
if (parent[finish] == 0) {
break;
}
T fmin = INF;
for (size_t node = finish; node != start; node = parent[node]) {
fmin = min(fmin, capacity_[parent[node]][node] - flow_[parent[node]][node]);
}
if (fmin == 0) {
continue;
}
for (size_t node = finish; node != start; node = parent[node]) {
flow_[parent[node]][node] += fmin;
flow_[node][parent[node]] -= fmin;
}
flow += fmin;
cost += read_dist[finish] * fmin;
}
flow_val_ = flow;
cost_val_ = cost;
return {flow, cost};
}
};
int main() {
freopen("fmcm.in", "r", stdin);
freopen("fmcm.out", "w", stdout);
int n, m, start, finish;
cin >> n >> m >> start >> finish;
MaxFlowMinimalCost<int> flow(n);
for (int i = 0; i < m; ++ i) {
int x, y, cap, cost;
cin >> x >> y >> cap >> cost;
flow.add_edge(x, y, cap, cost);
}
auto res = flow.do_flow(start, finish);
// cerr << res.first << endl;
cout << res.second << endl;
return 0;
}