• POJ 2112 Optimal Milking【网络流+二分+最短路】


    求使所有牛都可以被挤牛奶的条件下牛走的最长距离。

    Floyd求出两两节点之间的最短路,然后二分距离。

    构图:

    将每一个milking machine与源点连接,边权为最大值m,每个cow与汇点连接,边权为1,然后根据二分的距离x,将g[i][j] < x的milking machine节点i与cow节点j连接,边权为1,其他的赋值为零。

    最大流的结果是可以被挤奶的cow数量,判断是否等于总的cow总量即可。


    #include <iostream>
    #include <cstring>
    #include <vector>
    #include <cstdio>
    #include <algorithm>
    using namespace std;
    #define N 240
    #define INF 0x3f3f3f3f
    
    class Dinic {
    public:
        int n, s, t, l[N], c[N][N], e[N];
        int flow(int maxf = INF) {
            int left = maxf;
            while (build()) left -= push(s, left);
            return maxf - left;
        }
        int push(int x, int f) {
            if (x == t) return f;
            int &y = e[x], sum = f;
            for (; y<n; y++)
                if (c[x][y] > 0 && l[x]+1==l[y]) {
                    int cnt = push(y, min(sum, c[x][y]));
                    c[x][y] -= cnt;
                    c[y][x] += cnt;
                    sum -= cnt;
                    if (!sum) return f;
                }
            return f-sum;
        }
        bool build() {
            int m = 0;
            memset(l, -1, sizeof(l));
            l[e[m++]=s] = 0;
            for (int i=0; i<m; i++) for (int y=0; y<n; y++)
                if (c[e[i]][y] > 0 && l[y]<0) l[e[m++]=y] = l[e[i]] + 1;
            memset(e, 0, sizeof(e));
            return l[t] >= 0;
        }
    } net;
    int g[N][N], n, k, c, m;
    
    bool ok(int x) {
        memset(net.c, 0, sizeof(net.c));
        net.s = 0, net.t = n + 1, net.n = n + 2;
    
        for (int i=1; i<=k; i++) net.c[0][i] = m;
        for (int i=k+1; i<=n; i++) net.c[i][net.t] = 1;
    
        for (int i=1; i<=k; i++)
            for (int j=k+1; j<=n; j++)
                if (g[i][j] <= x) net.c[i][j] = 1;
                else net.c[i][j] = 0;
    
        return net.flow() == c;
    }
    int main() {
    
        while (scanf("%d%d%d", &k, &c, &m) == 3) {
            n = k + c;
            for (int i=1; i<=n; i++)
                for (int j=1; j<=n; j++) {
                    scanf(" %d", &g[i][j]);
                    if (g[i][j] == 0 && i != j) g[i][j] = INF;
                }
            for (int p=1; p<=n; p++) for (int i=1; i<=n; i++)
                for (int j=1; j<=n; j++) g[i][j] = min(g[i][j], g[i][p] + g[p][j]);
    
            int l = 0, r = INF, mid, ans;
            while (l <= r) {
                mid = (l + r) >> 1;
                if (ok(mid)) {
                    ans = mid;
                    r = mid -1;
                } else l = mid + 1;
            }
            cout << ans << endl;
        }
        return 0;
    }
    
    
    
    


  • 相关阅读:
    iframe脸面的页面和父页面之间的交互方法
    iframe高度自适应
    获取html元素所在页面的坐标
    自制的几个jquery插件
    将DataTable转换成Json格式
    QL 获取当前日期,年、月、日、周、时、分、秒
    DropdownList异步刷新GridView数据
    图片热区——map的用法
    Chart控件文档
    母版页改变被嵌套的页面中的控件ID的解决方法
  • 原文地址:https://www.cnblogs.com/snake-hand/p/3141107.html
Copyright © 2020-2023  润新知