zoukankan      html  css  js  c++  java
  • POJ 2112 Optimal Milking 最短路 二分构图 网络流

    题意:有C头奶牛,K个挤奶站,每个挤奶器最多服务M头奶牛,奶牛和奶牛、奶牛和挤奶站、挤奶站和挤奶站之间都存在一定的距离。现在问满足所有的奶牛都能够被挤奶器服务到的情况下,行走距离的最远的奶牛的至少要走多远。题目给的邻接矩阵是K个挤奶站与C个奶牛的距离矩阵,其中0为不可达的意思。

    刚刷网络流,第一次遇到这样题目,题意我就看了半天才懂。。此题需要将题给条件转化,最后利用二分枚举距离,将每次情况建立一个新的图再网络流得解。

    思路: 需要首先用Floyd将各个站与奶牛的最短距离得出,然后利用二分,左边界=0,右边界=题给每条路最大权值*最大可能走的路数=200*(K+C)。

    然后将每次枚举的mid比较图中的边权,因为要枚举的是最大距离(的最小值,但最大距离的性质肯定还是有的,即大于等于其他边),所以边权<=mid的加入网络流图中且权重为1,那些大于mid的边就当作该情况下不用走的,即可忽略。

    将K与C以此建立网络流,并且设一个超级源点S与超级汇点T,S指向所有挤奶站K切边权为题给容量M,所有奶牛流向T边权为1。若最大流结果等于C说明该次枚举情况符合,便继续缩小枚举范围,若最大流结果小于C,说明边权限制过小则要增大枚举范围。一直反复枚举则得结果。

    (代码转自https://www.cnblogs.com/Lyush/archive/2013/04/30/3052077.html)

      1 #include <cstdlib>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <iostream>
      5 #include <algorithm>
      6 using namespace std;
      7 
      8 int K, C, M; // K个挤奶器,C头奶牛,每个挤奶器最多M头奶牛共享
      9 int N;
     10 int mp[250][250];
     11 
     12 struct Edge {
     13     int v, c, next;    
     14 };
     15 
     16 Edge e[100000];
     17 int idx, head[250];
     18 int lv[250];
     19 int front, tail, que[250];
     20 const int SS = 0, TT = 248;
     21 const int INF = 0x3fffffff;
     22 
     23 void insert(int a, int b, int c) {
     24     e[idx].v = b, e[idx].c = c;
     25     e[idx].next = head[a];
     26     head[a] = idx++;
     27 }
     28 
     29 void floyd() { // 求出任意两点之间的最短路 
     30     for (int k = 1; k <= N; ++k) {
     31         for (int i = 1; i <= N; ++i) {
     32             if (mp[i][k] == INF || i == k) continue;
     33             for (int j = 1; j <= N; ++j) {
     34                 if (mp[k][j] == INF || j == k) continue;
     35                 mp[i][j] = min(mp[i][j], mp[i][k] + mp[k][j]);
     36             }
     37         }
     38     }
     39 }
     40 
     41 void build(int threshold) { // 阀值 
     42     idx = 0;
     43     memset(head, 0xff, sizeof (head));
     44     for (int i = 1; i <= K; ++i) {
     45         insert(SS, i, M);
     46         insert(i, SS, 0);
     47         for (int j = K+1; j <= N; ++j) {
     48             if (mp[i][j] <= threshold) {
     49                 insert(i, j, 1);
     50                 insert(j, i, 0);
     51             }
     52         }
     53     }
     54     for (int i = K+1; i <= N; ++i) {
     55         insert(i, TT, 1);
     56         insert(TT, i, 0);
     57     }
     58 }
     59 
     60 bool bfs() {
     61     front = tail = 0;
     62     memset(lv, 0xff, sizeof (lv));
     63     lv[SS] = 0;
     64     que[tail++] = SS;
     65     while (front != tail) {
     66     //    printf("front = %d, tail = %d
    ", front, tail);
     67         int u = que[front++];
     68         for (int i = head[u]; i != -1; i = e[i].next) {
     69             if (!(~lv[e[i].v]) && e[i].c) {
     70                 lv[e[i].v] = lv[u] + 1;
     71                 if (e[i].v == TT) return true;
     72                 que[tail++] = e[i].v;
     73             }    
     74         }
     75     }
     76     return ~lv[TT];
     77 }
     78 
     79 int dfs(int u, int sup) {
     80     if (u == TT) return sup;
     81     int tf = 0, f;
     82     for (int i = head[u]; i != -1; i = e[i].next) {
     83         if (lv[u]+1==lv[e[i].v] && e[i].c && (f=dfs(e[i].v, min(e[i].c, sup-tf)))) {
     84             tf += f;
     85             e[i].c -= f, e[i^1].c += f;
     86             if (tf == sup) return sup;
     87         }
     88     }
     89     if (!tf) lv[u] = -1;
     90     return tf;
     91 }
     92 
     93 int dinic() {
     94     int ret = 0;
     95     while (bfs()) {
     96         ret += dfs(SS, INF);
     97     }
     98     return ret;
     99 } 
    100 
    101 int bsearch(int l, int r) {
    102     int mid, ret;
    103     while (l <= r) {
    104         mid = (l + r) >> 1;
    105         if (build(mid), dinic() == C) {
    106             ret = mid;
    107             r = mid - 1;
    108         } else {
    109             l = mid + 1;
    110         }
    111     }
    112     return ret;
    113 }
    114 
    115 int main() {
    116     while (scanf("%d %d %d", &K, &C, &M) != EOF) {
    117         N = K+C;    
    118         memset(mp, 0, sizeof (mp));
    119         for (int i = 1; i <= N; ++i) {
    120             for (int j = 1; j <= N; ++j) {
    121                 scanf("%d", &mp[i][j]);
    122                 if (!mp[i][j]) mp[i][j] = INF;
    123             }
    124         }
    125         floyd();
    126         printf("%d
    ", bsearch(1, 1000000));
    127     }
    128     return 0;
    129 }
    View Code

     

    适当比较,砥砺前行
  • 相关阅读:
    Delphi中QuotedStr介绍及使用
    <<编写可维护的JavaScript>>之避免使用全局变量
    JavaScript中的继承模式总结(九)
    JavaScript中的继承(原型链)
    Javascript中函数的四种调用方式
    apply()和call()的区别
    在mui中遇到的内容覆盖导航栏的问题
    相等(==)运算符和等同(===)运算符之间的区别
    理解Javascript参数中的arguments对象
    Javascript之类型检测(一)
  • 原文地址:https://www.cnblogs.com/llllrj/p/9388476.html
Copyright © 2011-2022 走看看