您的位置:首页 > 理论基础 > 计算机网络

BZOJ1834 [ZJOI2010]network 网络扩容

2014-12-14 17:16 274 查看
网络流训练好题。。。但是要给差评!蒟蒻表示这就是板子题,然后做了半个小时T T

先跑一边最大流,得到第一问答案ans。

第二问:原先的边不动,费用为0。

然后对每条边在上面再加一条边,流量为inf,费用为修改费用。

n向T连一条边,流量为ans + k,费用为0。

跑一边费用流即可。

/**************************************************************
Problem: 1834
User: rausen
Language: C++
Result: Accepted
Time:64 ms
Memory:1296 kb
****************************************************************/

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;
const int N = 1005;
const int M = 10005;
const int inf = (int) 1e9;

struct Edges {
int x, y, c, w;
} E[M];

struct edges {
int next, to, f, cost;
edges() {}
edges(int _n, int _t, int _f, int _c) : next(_n), to(_t), f(_f), cost(_c) {}
} e[M << 1];

int n, m, k, last_ans;
int S, T;
int first
, tot;
int q
, d
, g
;
bool v
;

inline int read() {
int x = 0, sgn = 1;
char ch = getchar();
while (ch < '0' || '9' < ch) {
if (ch == '-') sgn = -1;
ch = getchar();
}
while ('0' <= ch && ch <= '9') {
x = x * 10 + ch - '0';
ch = getchar();
}
return sgn * x;
}

inline void Add_Edges(int x, int y, int f, int c) {
e[++tot] = edges(first[x], y, f, c), first[x] = tot;
e[++tot] = edges(first[y], x, 0, -c), first[y] = tot;
}

bool bfs() {
memset(d, 0, sizeof(d));
q[1] = S, d[S] = 1;
int l, r, x, y;
for (l = r = 1; l != (r + 1) % N; (++l) %= N)
for (x = first[q[l]]; x; x = e[x].next){
y = e[x].to;
if (!d[y] && e[x].f)
q[(++r) %= N] = y, d[y] = d[q[l]] + 1;
}

return d[T];
}

int dinic(int p, int limit) {
if (p == T || !limit) return limit;
int x, y, tmp, rest = limit;
for (x = first[p]; x; x = e[x].next)
if (d[y = e[x].to] == d[p] + 1 && e[x].f && rest) {
tmp = dinic(y, min(rest, e[x].f));
rest -= tmp;
e[x].f -= tmp, e[x ^ 1].f += tmp;
if (!rest) return limit;
}
if (limit == rest) d[p] = 0;
return limit - rest;
}

int Dinic() {
int res = 0, x;
while (bfs())
res += dinic(S, inf);
return res;
}

void work1() {
int i;
memset(first, 0, sizeof(first));
for (i = tot = 1; i <= m; ++i)
Add_Edges(E[i].x, E[i].y, E[i].c, 0);
S = 1, T = n;
printf("%d ", last_ans = Dinic());
}

inline int calc() {
int flow = inf, x;
for (x = g[T]; x; x = g[e[x ^ 1].to])
flow = min(flow, e[x].f);
for (x = g[T]; x; x = g[e[x ^ 1].to])
e[x].f -= flow, e[x ^ 1].f += flow;
return flow;
}

bool spfa() {
int x, y, l, r;
for (x = 1; x <= T; ++x)
d[x] = inf;
d[S] = 0, v[S] = 1, q[0] = S;
for(l = r = 0; l != (r + 1) % N; ++l %= N) {
for (x = first[q[l]]; x; x = e[x].next)
if (d[q[l]] + e[x].cost < d[y = e[x].to] && e[x].f) {
d[y] = d[q[l]] + e[x].cost;
g[y] = x;
if (!v[y])
q[(++r) %= N] = y, v[y] = 1;
}
v[q[l]] = 0;
}
return d[T] != inf;
}

inline int work() {
int res = 0;
while (spfa())
res += calc() * d[T];
return res;
}

void work2() {
int i;
memset(first, 0, sizeof(first));
for (i = tot = 1; i <= m; ++i) {
Add_Edges(E[i].x, E[i].y, E[i].c, 0);
Add_Edges(E[i].x, E[i].y, inf, E[i].w);
}
Add_Edges(n, n + 1, last_ans + k, 0);
S = 1, T = n + 1;
printf("%d\n", work());
}

int main() {
int i;
n = read(), m = read(), k = read();
for (i = 1; i <= m; ++i)
E[i].x = read(), E[i].y = read(), E[i].c = read(), E[i].w = read();
work1();
work2();
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: