Pagini recente » Cod sursa (job #2338380) | Cod sursa (job #879172) | Cod sursa (job #2343177) | Cod sursa (job #3274473) | Cod sursa (job #2963268)
#include <bits/stdc++.h>
using namespace std;
#ifndef LOCAL
ifstream in("fmcm.in");
ofstream out("fmcm.out");
#define cin in
#define cout out
#endif // LOCAL
struct MCMF {
struct Edge {
int from, to, flow, cap, cost;
};
static const int buffer = 7;
int n, source, sink;
vector<Edge> edges;
vector<vector<int>> edge_ids;
vector<int> potential;
vector<int> coming;
MCMF(int _n, int _source, int _sink) {
n = _n; source = _source; sink = _sink;
edge_ids.resize(n + buffer);
potential.resize(n + buffer);
coming.resize(n + buffer);
}
void add_edge(int from, int to, int cap, int cost) {
edge_ids[from].push_back(edges.size()); edges.push_back({from, to, 0, cap, cost});
edge_ids[to].push_back(edges.size()); edges.push_back({to, from, 0, 0, -cost});
}
void bellman_ford() {
vector<int> dist(n + buffer, 0);
for(int i = 0; i < n + buffer; i++) {
for(int i = 0; i < edges.size(); i += 2) {
const auto& ed = edges[i];
dist[ed.to] = min(dist[ed.to], dist[ed.from] + ed.cost);
}
}
potential = dist;
}
bool dijkstra() {
const int INF = 1e9;
vector<int> dist(n + buffer, INF);
dist[source] = 0;
priority_queue<pair<int, int>> pq;
pq.push({-dist[source], source});
while(!pq.empty()) {
auto cnt = pq.top(); pq.pop();
if(dist[cnt.second] != -cnt.first) continue;
for(auto eid : edge_ids[cnt.second]) {
const auto &ed = edges[eid];
if(ed.flow == ed.cap) continue;
if(dist[ed.to] > dist[ed.from] + (ed.cost + potential[ed.from] - potential[ed.to])) {
dist[ed.to] = dist[ed.from] + (ed.cost + potential[ed.from] - potential[ed.to]);
coming[ed.to] = eid;
pq.push({-dist[ed.to], ed.to});
}
}
}
potential = dist;
return dist[sink] != INF;
}
int64_t flow = 0, cost = 0;
void compute() {
for(auto &e : edges) e.flow = 0;
flow = 0; cost = 0;
bellman_ford();
while(dijkstra()) {
int cnt_flow = 1e9;
for(int x = sink; x != source; x = edges[coming[x]].from) {
cnt_flow = min(cnt_flow, edges[coming[x]].cap - edges[coming[x]].flow);
}
flow += cnt_flow;
for(int x = sink; x != source; x = edges[coming[x]].from) {
edges[coming[x] ^ 0].flow += cnt_flow;
edges[coming[x] ^ 1].flow -= cnt_flow;
cost += 1LL * edges[coming[x]].cost * cnt_flow;
}
}
}
int64_t max_flow() {
compute(); return flow;
}
int64_t min_cost() {
compute(); return cost;
}
};
int main() {
int n, m, s, d; cin >> n >> m >> s >> d;
MCMF mcmf(n, s, d);
for(int i = 0; i < m; i++) {
int x, y, cap, cost; cin >> x >> y >> cap >> cost;
mcmf.add_edge(x, y, cap, cost);
}
#ifdef LOCAL
cerr << mcmf.max_flow() << endl;
#endif // LOCAL
cout << mcmf.min_cost() << endl;
}