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

POJ-2391 Ombrophobic Bovines 网络流-拆点构图

2013-04-30 23:31 267 查看
题意:有F快草地,每块草地上有若干奶牛也有避雨点,每个避雨点只能够容纳一定量的奶牛。草地之间有边。现在问所有牛全部到达避雨点的时间是多少?

解法:这题和POJ-2112非常相似,做法也差不多,folyd处理之后二分枚举答案。该题的构图稍微难一点,需要考虑到一个流量的控制问题,即当某一点多余的流量流出去后必须在下一个点停止住。自己是把一个点拆成了3个点进行控制,后面学习了别人拆成两个点也能完成。

代码如下:

#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

typedef long long LL;
const long long INF = 0x3f3f3f3f3f3f3f3fLL;
int F, P, sum;
const int SS = 402, TT = 403;

struct Edge {
int v, c, next;
};
Edge e[200000];
LL mp[205][205];
int in[405], out[405];
int idx, head[405], lv[405];
int front, tail, que[405];

void floyd() {
for (int k = 1;k <= F; ++k) {
for (int i = 1; i <= F; ++i) {
if (mp[i][k] == INF || i == k) continue;
for (int j = 1; j <= F; ++j) {
if (mp[k][j] == INF || j == k) continue;
mp[i][j] = min(mp[i][j], mp[i][k] + mp[k][j]);
}
}
}
}

void insert(int a, int b, int c) {
e[idx].v = b, e[idx].c = c;
e[idx].next = head[a];
head[a] = idx++;
}

void build(LL threshold) {
idx = 0;
memset(head, 0xff, sizeof (head));
for (int i = 1; i <= F; ++i) {
if (in[i]) {
insert(SS, i, in[i]), insert(i, SS, 0);
}
insert(i, 200+i, 1000000), insert(200+i, i, 0);
if (out[i]) {
insert(200+i, TT, out[i]), insert(TT, 200+i, 0);
}
for (int j = 1; j <= F; ++j) {
if (mp[i][j] <= threshold) {
insert(i, j+200, 1000000);
insert(j+200, i, 0);
}
}
}
}

bool bfs() {
memset(lv, 0xff, sizeof (lv));
front = tail = lv[SS] = 0;
que[tail++] = SS;
while (front < tail) {
int u = que[front++];
for (int i = head[u]; i != -1; i = e[i].next) {
if (!(~lv[e[i].v]) && e[i].c) {
lv[e[i].v] = lv[u] + 1;
if (e[i].v == TT) return true;
que[tail++] = e[i].v;
}
}
}
return false;
}

int dfs(int u, int sup) {
if (u == TT) return sup;
int tf = 0, f;
for (int i = head[u]; i != -1; i = e[i].next) {
if (lv[u]+1==lv[e[i].v] && e[i].c && (f=dfs(e[i].v, min(e[i].c, sup-tf)))) {
tf += f;
e[i].c -= f, e[i^1].c += f;
if (tf == sup) return sup;
}
}
if (!tf) lv[u] = -1;
return tf;
}

int dinic() {
int ret = 0;
while (bfs()) {
ret += dfs(SS, 1000000);
}
return ret;
}

LL bsearch(LL l, LL r) {
LL ret = -1, mid;
while (l <= r) {
mid = (l + r) >> 1;
if (build(mid), dinic() == sum) {
r = mid - 1;
ret = mid;
} else {
l = mid + 1;
}
}
return ret;
}

int main() {
int a, b;
LL c;
while (scanf("%d %d", &F, &P) != EOF) {
sum = 0;
memset(mp, 0x3f, sizeof (mp));
for (int i = 1; i <= F; ++i) {
scanf("%d %d", &in[i], &out[i]);
sum += in[i];
}
for (int i = 1; i <= P; ++i) {
scanf("%d %d %I64d", &a, &b, &c);
if (c < mp[a][b]) {
mp[a][b] = mp[b][a] = c;
}
}
floyd();
printf("%I64d\n", bsearch(0, INF-1));
// 不减去1,那么-1将会输出INF......
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: