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

题意:有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; }

 

posted @ 2013-04-30 23:31  沐阳  阅读(267)  评论(0编辑  收藏  举报