洛谷
#include<bits/stdc++.h>
using namespace std;
const int N = 50005, M = 50000 * 2 + 5;
int h[N], e[M], ne[M], flow[M], cost[M], idx;
int n, m, S, T;
int dist[N], pre[N];
bool st[N];
void add(int a, int b, int v, int c) {
flow[idx] = v, cost[idx] = c, e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}
bool spfa() { //找最短路,因为有负权边,所以用改良的Ford,即是spfa()
for (int i = 1; i <= n; i++) dist[i] = 2e9, st[i] = false, pre[i] = -1;
dist[S] = 0;
queue<int> q;
q.push(S);
st[S] = true;
while (q.size()) {
int x = q.front();
q.pop();
st[x] = false;
for (int i = h[x]; ~i; i = ne[i]) {
int j = e[i];
if (flow[i] && dist[j] > dist[x] + cost[i]) {
dist[j] = dist[x] + cost[i];
pre[j] = i; //记录一下该点是由那条边扩展而来的
if (!st[j]) st[j] = true, q.push(j);
}
}
}
if (pre[T] == -1) return false; //看T是否在余图中
return true;
}
int maxflow(int &c) { //返回最大流量,c是对应的最小花费
int res = 0;
while (spfa()) {
int minv = INT_MAX, cur = pre[T];
while (cur != -1)
minv = min(minv, flow[cur]), cur = pre[e[cur ^ 1]]; //从末点向前推,得到所能增加的最大流量
cur = pre[T];
while (cur != -1)
flow[cur] -= minv, flow[cur ^ 1] += minv, c += cost[cur] * minv, cur = pre[e[cur ^ 1]]; //对应的修改余图
res += minv;
}
return res;
}
int main() {
memset(h, -1, sizeof h);
cin >> n >> m >> S >> T;
while (m--) {
int x, y, z, c;
scanf("%d%d%d%d", &x, &y, &z, &c);
add(x, y, z, c), add(y, x, 0, -c);
}
int c = 0;
int ans = maxflow(c);
cout << ans << ' ' << c << endl;
return 0;
}