zoukankan      html  css  js  c++  java
  • POJ 2112 Optimal Milking (二分 + 最大流)

    题目大意:

    在一个农场里面,有k个挤奶机,编号分别是 1..k,有c头奶牛,编号分别是k+1 .. k+c,每个挤奶机一天最让可以挤m头奶牛的奶,奶牛和挤奶机之间用邻接矩阵给出距离。求让所有奶牛都挤到

    奶的情况下,走的最远的那头奶牛走的距离最小是多少。

    数据保证有解。

    算法讨论:

    首先可以想到是二分,然后在选择流网络的时候,一开始选择的最小费用最大流,让二分的边权充当最小费用,但是这样跑发现每次二分的是我们要跑的答案,不可行。所以就改用最大流。

    最大流肯定是在二分的情况下判定最大流是否等于c,即是否所有的奶牛都可以挤到奶,所以一开始我的做法是直接把所有的边都加进去,然后在跑bfs的时候把边权大于二分值的边卡掉,但是发现这样是不可行的,(至于为什么不可行,有待思考。。。。)然后另一种做法就是每一次二分的时候都是重新加边(当前是小于二分值的边),然后跑最大流。但是不知道为什么我跑出来那么的效率低下。加边就是这样加:从超级源点向每头牛加流量为1的边,每头牛向距离小于二分当前值的挤奶机加流量为1的边,每个挤奶机向超级汇点加流量为m的边,根据入流等于出流的原理,这样就可以保证每个挤奶机至多只挤m头牛的奶了。

    Codes:

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <cstdlib>
      5 #include <algorithm>
      6 #include <queue>
      7 
      8 using namespace std;
      9 
     10 int k, c, mm, l, r, Mid;
     11 int arr[250][250];
     12 
     13 struct MF{
     14     static const int N = 230 + 5;
     15     static const int M = 300 * 300 + 5;
     16     static const int oo = 0x3f3f3f3f;
     17     
     18     int n, m, s, t, tot;
     19     int first[N], next[M];
     20     int u[M], v[M], cap[M], flow[M];
     21     int dis[N], cur[N];
     22     bool vi[M];
     23     
     24     void Clear(){
     25         tot = 0;
     26         memset(first, -1, sizeof first);
     27         memset(flow, 0 ,sizeof flow);
     28     }
     29     void Add(int from, int to, int cp, int flw){
     30         u[tot] = from; v[tot] = to; cap[tot] = cp; flow[tot] = flw;
     31         next[tot] = first[u[tot]];
     32         first[u[tot]] = tot;
     33         ++ tot;
     34     }
     35     bool bfs(){
     36         memset(vi, false, sizeof vi);
     37 
     38         queue <int> q;
     39         dis[s] = 0;vi[s] = true;
     40         q.push(s);
     41         
     42         while(!q.empty()){
     43             int now = q.front();q.pop();
     44             for(int i = first[now]; i != -1; i = next[i]){
     45                 if(!vi[v[i]] && cap[i] > flow[i]){
     46                     vi[v[i]] = true;
     47                     dis[v[i]] = dis[now] + 1;
     48                     q.push(v[i]);
     49                 }
     50             }
     51         }
     52         return vi[t];
     53     }    
     54     int dfs(int x, int a){
     55         if(x == t || a == 0) return a;
     56         int flw = 0, f;
     57         int &i = cur[x];
     58         for(i = first[x]; i != -1; i = next[i]){
     59             if(dis[x] + 1 == dis[v[i]] && (f = dfs(v[i], min(a, cap[i]-flow[i]))) > 0){
     60                 flow[i] += f; flow[i^1] -= f;
     61                 a -= f; flw += f;
     62                 if(a == 0) break;
     63             }
     64         }
     65         return flw;
     66     }
     67     int MaxFlow(int s, int t){
     68         this->s = s;this->t = t;
     69         int flw = 0;
     70         while(bfs()){
     71             memset(cur, 0, sizeof cur);
     72             flw += dfs(s, oo);
     73         }
     74         return flw;
     75     }
     76 }Net;
     77 
     78 void Floyed(){
     79     for(int kk = 1; kk <= k + c; ++ kk)
     80         for(int i = 1; i <= k + c; ++ i)
     81             for(int j = 1; j <= k + c; ++ j)
     82                 if(kk != i && i != j && kk != j)
     83                     if(arr[i][kk] < 1000000 && arr[kk][j] < 1000000)
     84                         arr[i][j] = min(arr[i][j], arr[i][kk] + arr[kk][j]);
     85 }
     86 
     87 bool check(){
     88     Net.Clear();
     89     for(int i = 1; i <= c; ++ i){
     90         Net.Add(0, i + k, 1, 0);
     91         Net.Add(i + k, 0, 0, 0);
     92     }
     93     for(int i = 1; i <= k; ++ i){
     94         Net.Add(i, Net.n + 1, mm, 0);
     95         Net.Add(Net.n + 1, i, 0, 0);
     96     }
     97     for(int i = k + 1; i <= k + c; ++ i){
     98         for(int j = 1; j <= k; ++ j){
     99             if(arr[i][j] <= Mid){
    100                 Net.Add(i, j, 1, 0);
    101                 Net.Add(j, i, 0, 0);
    102             }
    103         }
    104     }
    105     if(Net.MaxFlow(0, Net.n + 1) == c) return true;
    106     return false;
    107 }
    108 
    109 void Solve(){
    110     int ans=0;l = 1;r = 10000;
    111     while(l <= r){
    112         Mid = l + (r - l) / 2;
    113         if(check()){
    114             ans = Mid;r = Mid - 1;
    115         }
    116         else l = Mid + 1;
    117     }
    118     printf("%d
    ", ans);
    119 }
    120 int main(){
    121 
    122     scanf("%d%d%d", &k, &c, &mm);
    123     Net.n = k + c;
    124     memset(arr, 127/3, sizeof arr);
    125     for(int i = 1; i <= k + c; ++ i)
    126         for(int j = 1; j <= k + c; ++ j){
    127             scanf("%d", &arr[i][j]);
    128             arr[i][j] = arr[i][j] == 0 ? Net.oo : arr[i][j];
    129         }
    130     Floyed();
    131     Solve();
    132     return 0;
    133 }
    POJ 2112
  • 相关阅读:
    (4)路由器和交换机区别
    (3)arp协议
    (2)OSi模型
    (1)网络基础概念
    探索JVM底层奥秘ClassLoader源码分析
    数据库类型对应Java语言类型表
    JSON空值处理与 StringUtils工具类使用
    props、state、forms
    React官方中文文档【安装】
    搭建React项目环境【1】
  • 原文地址:https://www.cnblogs.com/sxprovence/p/5108022.html
Copyright © 2011-2022 走看看