bzoj1834 [ZJOI2010]network 网络扩容
给定一张有向图,每条边都有一个容量 (C) 和一个扩容费用 (W) ,即将容量扩大 (1) 所需的费用。
求:
- (1) 到 (N) 的最大流;
- 将 (1) 到 (N) 的最大流增加 (K) 所需的最小扩容费用。
(nleq10^3, mleq5 imes10^3, kleq10)
费用流
对于原图中的边 ((u, v, w, c)) ,连边 ((u, v, w, 0), (u, v, inf, c))
限制 (K) 的流量可以连边 ((T, T', K, 0)) 或 ((S', S, K, 0))
时间复杂度 (O() 能过 ())
代码
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1010, maxm = 1e4 + 10, inf = 1 << 30;
int N, M, K;
namespace maxflow {
static int S, T, q[maxn], h[maxn], f[maxn], pre[maxn];
static struct edges {
int nxt, to, w;
edges(int x = 0, int y = 0, int z = 0) :
nxt(x), to(y), w(z) {}
} e[maxm];
void addline(int u, int v, int w) {
static int cnt = 1;
e[++cnt] = edges(h[u], v, w), h[u] = cnt;
e[++cnt] = edges(h[v], u, 0), h[v] = cnt;
}
bool bfs() {
memset(f, 0, sizeof f);
int l = 1, r = 1;
q[1] = S, f[S] = inf;
while (l <= r) {
int u = q[l++];
for (int i = h[u]; i; i = e[i].nxt) {
int v = e[i].to;
if (e[i].w && !f[v]) {
pre[v] = i, q[++r] = v;
f[v] = min(f[u], e[i].w);
if (v == T) return 1;
}
}
}
return 0;
}
int EK() {
int res = 0;
while (bfs()) {
for (int u = T; u != S; u = e[pre[u] ^ 1].to) {
e[pre[u]].w -= f[T], e[pre[u] ^ 1].w += f[T];
}
res += f[T];
}
return res;
}
}
namespace mcmf {
static bool vis[maxn];
static int S, T, h[maxn], f[maxn], dis[maxn], pre[maxn];
static struct edges {
int nxt, to, w, c;
edges(int _n = 0, int _t = 0, int _w = 0, int _c = 0) :
nxt(_n), to(_t), w(_w), c(_c) {}
} e[maxm << 1];
static queue <int> q;
void addline(int u, int v, int w, int c) {
static int cnt = 1;
e[++cnt] = edges(h[u], v, w, c), h[u] = cnt;
e[++cnt] = edges(h[v], u, 0, -c), h[v] = cnt;
}
bool spfa() {
memset(dis, 0x3f, sizeof dis);
q.push(S), dis[S] = 0, f[S] = inf;
while (!q.empty()) {
int u = q.front();
q.pop(), vis[u] = 0;
for (int i = h[u]; i; i = e[i].nxt) {
int v = e[i].to;
if (e[i].w && dis[v] > dis[u] + e[i].c) {
pre[v] = i;
dis[v] = dis[u] + e[i].c;
f[v] = min(f[u], e[i].w);
if (!vis[v]) vis[v] = 1, q.push(v);
}
}
}
return dis[T] < 1e9;
}
int EK() {
int res = 0;
while (spfa()) {
for (int u = T; u != S; u = e[pre[u] ^ 1].to) {
e[pre[u]].w -= f[T], e[pre[u] ^ 1].w += f[T];
}
res += f[T] * dis[T];
}
return res;
}
}
int main() {
scanf("%d %d %d", &N, &M, &K);
for (int i = 1; i <= M; i++) {
int u, v, w, c;
scanf("%d %d %d %d", &u, &v, &w, &c);
maxflow::addline(u, v, w);
mcmf::addline(u, v, w, 0);
mcmf::addline(u, v, inf, c);
}
maxflow::S = 1;
maxflow::T = N;
int tmp = maxflow::EK();
mcmf::S = 1;
mcmf::T = N + 1;
mcmf::addline(N, N + 1, tmp + K, 0);
printf("%d %d", tmp, mcmf::EK());
return 0;
}