Pagini recente » Cod sursa (job #1962670) | Cod sursa (job #2204033) | Cod sursa (job #3270576) | Cod sursa (job #2527093) | Cod sursa (job #2907151)
#include <fstream>
#include <iostream>
#include <queue>
#include <set>
#include <vector>
using namespace std;
struct Graph {
vector<vector<int>> edges;
vector<vector<int>> ordered;
vector<vector<int>> cap;
vector<vector<int>> cost;
vector<int> h;
int src;
int dst;
Graph(int nodes, int src, int dst)
: edges(nodes), ordered(nodes), cap(nodes, vector<int>(nodes, 0)),
cost(nodes, vector<int>(nodes, 0)), src(src), dst(dst) {
}
int Size() const {
return edges.size();
}
void AddEdge(int a, int b, int cap, int cost) {
this->edges[a].push_back(b);
this->edges[b].push_back(a);
this->ordered[a].push_back(b);
this->cap[a][b] = cap;
this->cost[a][b] = cost;
this->cost[b][a] = -cost;
}
};
vector<int> BellmanFord(const Graph& graph) {
vector<int> dist(graph.Size(), 1 << 30);
dist[graph.src] = 0;
queue<int> q;
q.push(graph.src);
while (!q.empty()) {
auto node = q.front();
q.pop();
for (const auto& next : graph.ordered[node]) {
auto new_dist = dist[node] + graph.cost[node][next];
if (new_dist < dist[next]) {
dist[next] = new_dist;
q.push(next);
}
}
}
return dist;
}
vector<pair<int, int>> FindPath(const Graph& graph) {
vector<int> dist(graph.Size(), 1 << 30);
vector<int> prev(graph.Size(), -1);
multiset<pair<int, int>> heap;
dist[graph.src] = 0;
heap.insert({dist[graph.src], graph.src});
while (!heap.empty()) {
auto kk = heap.begin()->first;
auto node = heap.begin()->second;
heap.erase(heap.begin());
if (kk > dist[node]) {
continue;
}
for (const auto& next : graph.edges[node]) {
auto new_dist = dist[node] + graph.cost[node][next];
if (new_dist < dist[next] && graph.cap[node][next] > 0) {
dist[next] = new_dist;
prev[next] = node;
heap.insert({dist[next], next});
}
}
}
vector<pair<int, int>> path;
for (auto node = graph.dst; prev[node] >= 0; node = prev[node]) {
path.push_back({prev[node], node});
}
return path;
}
int Flow(Graph& graph, const vector<pair<int, int>>& path) {
auto flow = 1 << 30;
for (const auto& edge : path) {
flow = min(flow, graph.cap[edge.first][edge.second]);
}
auto cost = 0;
for (const auto& edge : path) {
auto a = edge.first;
auto b = edge.second;
cost += flow * (graph.cost[a][b] - (graph.h[a] - graph.h[b]));
graph.cap[a][b] -= flow;
graph.cap[b][a] += flow;
}
return cost;
}
int MaxFlow(Graph& graph) {
auto cost = 0;
auto path = FindPath(graph);
while (!path.empty()) {
cost += Flow(graph, path);
path = FindPath(graph);
}
return cost;
}
int Solve(Graph& graph) {
auto h = BellmanFord(graph);
for (auto i = 0; i < graph.Size(); i += 1) {
for (const auto& j : graph.edges[i]) {
graph.cost[i][j] += h[i] - h[j];
}
}
graph.h = h;
return MaxFlow(graph);
}
int main() {
ifstream fin("fmcm.in");
ofstream fout("fmcm.out");
int nodes, edges;
fin >> nodes >> edges;
int src, dst;
fin >> src >> dst;
Graph graph(nodes, src - 1, dst - 1);
for (auto i = 0; i < edges; i += 1) {
int a, b, cap, cost;
fin >> a >> b >> cap >> cost;
graph.AddEdge(a - 1, b - 1, cap, cost);
}
auto res = Solve(graph);
fout << res << "\n";
return 0;
}