//
// Created by Visors on 2020/9/30.
//
// 题目名:【模板】最小费用最大流
// 题目来源:luogu
// 题目链接:https://www.luogu.com.cn/problem/P3381
// 算法:MCMF.cpp
// 用途:最小费用最大流
// 时间复杂度:O(TODO)
//
#include <bits/stdc++.h>
using namespace std;
const int oo = 0x3f3f3f3f;
typedef long long ll;
struct Edge {
int from; // 起点
int to; // 终点
int capacity; // 容量
int flow; // 流量
int cost; // 费用
int next; // 下条边
Edge() = default;
Edge(int from, int to, int capacity, int flow, int cost, int next) : from(from), to(to), capacity(capacity),
flow(flow), cost(cost), next(next) {}
};
// TODO v是flow,c是capacity
vector<Edge> edges; // 边集
vector<int> heads; // 首边集
vector<int> imps; // 可改进量
vector<int> paths; // 增广路后向弧
vector<int> dist; // s源最短路
vector<bool> inq; // SPFA队列
int n, m, s, t;
ll max_flow, min_cost;
inline void addEdge(int u, int v, int capacity, int flow, int cost) {
edges.emplace_back(u, v, capacity, flow, cost, heads[u]);
heads[u] = edges.size() - 1;
}
inline void addFlow(int u, int v, int capacity, int flow, int cost) {
addEdge(u, v, capacity, flow, cost);
addEdge(v, u, 0, -flow, -cost);
}
inline bool spfa() {
fill(dist.begin(), dist.end(), oo);
fill(inq.begin(), inq.end(), false);
dist[s] = 0;
inq[s] = true;
imps[s] = oo;
queue<int> q;
q.push(s);
while (!q.empty()) {
int u = q.front();
q.pop();
inq[u] = false;
for (int i = heads[u]; ~i; i = edges[i].next) {
Edge &e = edges[i];
int &v = e.to;
// 增广路上松弛
if (e.capacity > e.flow && dist[v] > dist[u] + e.cost) {
dist[v] = dist[u] + e.cost;
paths[v] = i;
imps[v] = min(imps[u], e.capacity - e.flow);
if (!inq[e.to]) {
q.push(v);
inq[v] = true;
}
}
}
}
if (dist[t] == oo) return false;
return true;
}
inline void augment() {
max_flow += imps[t];
min_cost += (ll) dist[t] * (ll) imps[t];
for (int u = t; u != s; u = edges[paths[u]].from) {
edges[paths[u]].flow += imps[t];
edges[paths[u] ^ 1].flow -= imps[t];
}
}
inline void mcmf() {
while (spfa()) augment();
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
cin >> n >> m >> s >> t;
s--, t--;
edges.clear();
heads.resize(n, -1);
imps.resize(n);
paths.resize(n);
dist.resize(n);
inq.resize(n);
for (int i = 1, u, v, w, c; i <= m; i++) {
cin >> u >> v >> w >> c;
addFlow(u - 1, v - 1, w, 0, c);
}
mcmf();
cout << max_flow << ' ' << min_cost << endl;
return 0;
}
MCMF (EK + SPFA)
最新推荐文章于 2022-08-22 23:02:01 发布