题目大意:最小费用最大流
题解:最小费用最大流
卡点:1.太久不打MCMF,反向弧费用未取相反数
C++ Code:
#include <cstdio>
#include <cstring>
#define maxn 5010
#define maxm 50100
using namespace std;
const int inf = 0x3f3f3f3f;
int n, m, S, T, MF;
int q[maxm], h, t;
int d[maxn], pre[maxn];
bool vis[maxn];
int head[maxn], cnt = 2;
struct Edge {
int to, nxt, w, cost;
} e[maxm << 1];
void add(int a, int b, int c, int d) {
e[cnt] = (Edge) {b, head[a], c, d}; head[a] = cnt;
e[cnt ^ 1] = (Edge) {a, head[b], 0, -d}; head[b] = cnt ^ 1;
cnt += 2;
}
inline int min(int a, int b) {return a < b ? a : b;}
bool spfa() {
memset(d, 0x3f, sizeof d);
d[q[h = t = 0] = S] = 0;
while (h <= t) {
int u = q[h++];
vis[u] = false;
for (int i = head[u]; i; i = e[i].nxt) {
int v = e[i].to;
if (e[i].w && d[v] > d[u] + e[i].cost) {
d[v] = d[u] + e[i].cost;
pre[v] = i;
if (!vis[v]) {
q[++t] = v;
vis[v] = true;
}
}
}
}
return d[T] != inf;
}
int update() {
int ans, mf = inf;
for (int i = pre[T]; i; i = pre[e[i ^ 1].to]) mf = min(mf, e[i].w);
ans = mf * d[T];
MF += mf;
for (int i = pre[T]; i; i = pre[e[i ^ 1].to]) e[i].w -= mf, e[i ^ 1].w += mf;
return ans;
}
void MCMF() {
int ans = 0;
while (spfa()) ans += update();
printf("%d %d
", MF, ans);
}
int main() {
scanf("%d%d%d%d", &n, &m, &S, &T);
for (int i = 0; i < m; i++) {
int a, b, c, d;
scanf("%d%d%d%d", &a, &b, &c, &d);
add(a, b, c, d);
}
MCMF();
return 0;
}