bzoj1834 [ZJOI2010]network 网络扩容
bzoj1834 [ZJOI2010]network 网络扩容
给定一张有向图,每条边都有一个容量 \(C\) 和一个扩容费用 \(W\) ,即将容量扩大 \(1\) 所需的费用。
求:
- \(1\) 到 \(N\) 的最大流;
- 将 \(1\) 到 \(N\) 的最大流增加 \(K\) 所需的最小扩容费用。
\(n\leq10^3,\ m\leq5\times10^3,\ k\leq10\)
费用流
对于原图中的边 \((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;
}