• POJ2112 Optimal Milking 二分+网络流


    题意:

    有K个挤奶站,C头奶牛,每个挤奶站每天最多只能够为M头奶牛服务,奶牛到奶牛,奶牛到挤奶站都有一个距离,问一天能够为所有的奶牛都挤奶的匹配方案中,选择最远的距离最小方案。

    解法:

    通过二分枚举来构建边的关系,然后用网络流求解是否所有的牛在满足条件的情况下是否都能够被挤奶。

    代码如下:

    #include <cstdlib>
    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    #define inf 0x3fffffff
    using namespace std;
    
    int K, C, M, idx;
    
    int G[250][250], head[250], SS = 240, TT = 241;
    
    int dis[250], que[250], front, tail;
    
    struct Node {
        int v, next, cap;
    }e[60000];
    
    void Floyd() {
        for (int k = 1; k <= K+C; ++k) {
            for (int i = 1; i <= K+C; ++i) {
                for (int j = 1; j <= K+C; ++j) {
                    if (G[i][k] != -1 && G[k][j] != -1) {
                        if (G[i][k] + G[k][j] < G[i][j] || G[i][j] == -1) {
                            // 如果某一点为-1的话,应该是直接更新的,这里被坑了 
                            G[i][j] = G[i][k] + G[k][j];
                        }
                    }
                }
            }
        }
        
    /*    for (int i = K+1; i <= K+C; ++i) {
            for (int j = 1; j <= K; ++j) {
                printf("%d %d = %d\n", i, j, G[i][j]);
            }    
        }
        system("pause");*/
    }
    
    void addedge(int x, int v, int cap) {
        ++idx;
        e[idx].v = v, e[idx].cap = cap;
        e[idx].next = head[x];
        head[x] = idx;
    }
    
    bool bfs() {
        int pos;
        memset(dis, 0xff, sizeof (dis));
        dis[SS] = 0;
        front = tail = 0;
        que[++tail] = SS;
        while (front != tail) {
            pos = que[++front];
            for (int i = head[pos]; i != -1; i = e[i].next) {
                int v = e[i].v, cap = e[i].cap;
                if (dis[v] == -1 && cap > 0) {
                    dis[v] = dis[pos] + 1;
                    que[++tail] = v;
                }
            }
        }
        return dis[TT] != -1;
    }
    
    int dfs(int u, int flow) {
        if (u == TT) {
            return flow;
        }
        int tf = 0, f;
        for (int i = head[u]; i != -1; i = e[i].next) {
            int v = e[i].v, cap = e[i].cap;
            if (dis[v] == dis[u]+1 && cap > 0 && (f = dfs(v, min(cap, flow)))) {
                e[i].cap -= f, e[i^1].cap += f;
                flow -= f;
                tf += f;
            }
        }
        if (tf == 0) dis[u] = -1;
        return tf;
    }
    
    int Dinic() {
        int ret = 0;
        while (bfs()) {
            ret += dfs(SS, inf);
        }
        return ret;
    }
    
    int bsearch(int l, int r) {
        int ret;
        while (l <= r) {
            int mid = (l + r) >> 1;
            memset(head, 0xff, sizeof (head));
            idx = -1;
            for (int i = 1; i <= K; ++i) { // 遍历所有的挤奶器 
                addedge(i, TT, M);// 边的容量就是其最大的限制量
                addedge(TT, i, 0);
            }
            for (int i = K+1; i <= K+C; ++i) { // 遍历所有的奶牛 
                addedge(SS, i, 1);
                addedge(i, SS, 0);
                for (int j = 1; j <= K; ++j) { // 枚举每头奶牛到挤奶器的距离 
                    if (G[i][j] != -1 && G[i][j] <= mid) {
                        addedge(i, j, 1);
                        addedge(j, i, 0);
                    }
                }
            } 
            if (Dinic() == C) {
                ret = mid;
                r = mid - 1;
            } else {
                l = mid + 1;
            }
        }
        return ret;
    }
    
    int main() {
        while (scanf("%d %d %d", &K, &C, &M) == 3) {
            // 前K个是挤奶站,后C个奶牛所在位置
            memset(G, 0xff, sizeof (G));
            for (int i = 1; i <= K+C; ++i) {
                for (int j = 1; j <= K+C; ++j) {
                    scanf("%d", &G[i][j]);
                    if (G[i][j] == 0) G[i][j] = -1;
                }
            }
            Floyd();
            // 右边界不是200,因为可能有点边是通过其他边传递过去的 
            printf("%d\n", bsearch(1, 50000));
        }
        return 0;
    }
  • 相关阅读:
    从乙方到甲方,我在做什么
    局域网ARP攻击防护
    【中间件安全】WebSphere安全加固规范
    【中间件安全】Jboss安全加固规范
    【中间件安全】IIS6安全加固规范
    【中间件安全】Weblogic 安全加固规范
    【中间件安全】Nginx 安全加固规范
    【中间件安全】Tomcat 安全加固规范
    openresty开发系列33--openresty执行流程之2重写赋值阶段
    openresty开发系列32--openresty执行流程之1初始化阶段
  • 原文地址:https://www.cnblogs.com/Lyush/p/2728656.html
Copyright © 2020-2023  润新知