Pagini recente » Cod sursa (job #2647613) | Cod sursa (job #530515) | Cod sursa (job #1449636) | Cod sursa (job #749747) | Cod sursa (job #2591221)
#include <iostream>
#include <fstream>
#include <limits>
#include <queue>
#include <vector>
using namespace std;
int Source, Sink, N, M;
vector<vector<int>> Flow, Capacity, Cost, Graph;
vector<int> daddy, old_dist, real_dist, DP;
void addEdge(int from, int to, int cap, int cst)
{
Graph[from].emplace_back(to);
Capacity[from][to] += cap;
Cost[from][to] += cst;
}
void bellmanFord(int k)
{
vector<bool> inQueue(N);
queue<int> Queue;
fill(old_dist.begin(), old_dist.end(), numeric_limits<int>::max());
Queue.push(k);
inQueue[k] = true;
old_dist[k] = 0;
while (!Queue.empty()) {
k = Queue.front();
Queue.pop();
inQueue[k] = false;
for (auto v: Graph[k])
if (old_dist[v] > old_dist[k] + Cost[k][v] && Capacity[k][v] > Flow[k][v]) {
old_dist[v] = old_dist[k] + Cost[k][v];
if (inQueue[v]) continue;
inQueue[v] = true;
Queue.push(v);
}
}
}
bool dijkstra(int k)
{
fill(DP.begin(), DP.end(), numeric_limits<int>::max());
fill(real_dist.begin(), real_dist.end(), numeric_limits<int>::max());
priority_queue<pair<int,int>> Heap;
Heap.push({-0, k});
DP[k] = 0;
real_dist[k] = 0;
while (!Heap.empty()) {
k = Heap.top().second;
int cost = -Heap.top().first;
Heap.pop();
if (DP[k] < cost) continue;
if (k == Sink) continue;
// old_dist[v] <= old_dist[k] + Cost[k][v] due to bellmanFord minimality
// so Cost[k][v] + old_dist[k] - old_dist[v] >= 0
for (auto v: Graph[k])
if (DP[v] > DP[k] + Cost[k][v] + old_dist[k] - old_dist[v] && Capacity[k][v] > Flow[k][v]) {
DP[v] = DP[k] + Cost[k][v] + old_dist[k] - old_dist[v];
real_dist[v] = real_dist[k] + Cost[k][v];
daddy[v] = k;
Heap.push({-DP[v], v});
}
}
old_dist = real_dist;
return DP[Sink] != numeric_limits<int>::max();
}
int main()
{
ifstream fin("fmcm.in");
ofstream fout("fmcm.out");
fin.sync_with_stdio(false);
fin.tie(0);
fout.sync_with_stdio(false);
fout.tie(0);
fin >> N >> M >> Source >> Sink;
--Source;
--Sink;
Graph.resize(N);
Flow.resize(N);
Capacity.resize(N);
Cost.resize(N);
daddy.resize(N);
old_dist.resize(N);
real_dist.resize(N);
DP.resize(N);
fill(Flow.begin(), Flow.end(), vector<int>(N));
fill(Capacity.begin(), Capacity.end(), vector<int>(N));
fill(Cost.begin(), Cost.end(), vector<int>(N));
for (int i = 0; i < M; ++i) {
int x, y, cap, cst;
fin >> x >> y >> cap >> cst;
--x;
--y;
addEdge(x, y, cap, cst);
addEdge(y, x, 0, -cst);
}
int maxFlow = 0;
int minCost = 0;
bellmanFord(Source);
while (dijkstra(Source)) {
int bottleNeck = numeric_limits<int>::max();
for (int k = Sink; bottleNeck > 0 && k != Source; k = daddy[k])
bottleNeck = min(bottleNeck, Capacity[daddy[k]][k] - Flow[daddy[k]][k]);
if (bottleNeck == 0) continue;
for (int k = Sink; k != Source; k = daddy[k]) {
Flow[daddy[k]][k] += bottleNeck;
Flow[k][daddy[k]] -= bottleNeck;
}
minCost += bottleNeck * real_dist[Sink];
}
fout << minCost << "\n";
return 0;
}