zoukankan      html  css  js  c++  java
  • poj 2112 floyd+Dinic最大流+二分最小值

      题目大意是:

        K台挤奶机器,C头牛,K不超过30,C不超过200,每台挤奶机器最多可以为M台牛工作,给出这些牛和机器之间,牛和牛之间,机器与机器之间的距离,在保证让最多的牛都有机器挤奶的情况下,给出其中距离最长的一头牛移动距离的最小值。

      首先用Floyd求出任意两点之间的最短距离,然后再用二分法限定最多的移动距离d,在求最大流时,搜索增广路的时候同时也判断距离有没有超过d就行了。

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <queue>
      4 #define _clr(x, y) memset(x, y, sizeof(x))
      5 #define Min(x, y) (x < y ? x : y)
      6 #define INF 0x3f3f3f3f
      7 #define N 1005
      8 using namespace std;
      9 
     10 int flow[N][N], dist[N][N];
     11 int level[N];
     12 int K, C, M,  S, T, ln;
     13 
     14 void Floyd()
     15 {
     16     for(int k=1; k<=ln; k++)
     17         for(int i=1;i<=ln; i++) if(dist[i][k]<INF)
     18             for(int j=1; j<=ln; j++)
     19                 if(dist[i][k]+dist[k][j]<dist[i][j])
     20                     dist[i][j] = dist[i][k]+dist[k][j];
     21 }
     22 
     23 bool bfs()
     24 {
     25     _clr(level, -1);
     26     level[S] = 0;
     27     queue<int> Q;
     28     Q.push(S);
     29     while(!Q.empty())
     30     {
     31         int u = Q.front();
     32         Q.pop();
     33         for(int i=0; i<=T; i++)
     34         {
     35             if(flow[u][i] && level[i]<0)
     36             {
     37                 level[i] = level[u] + 1;
     38                 Q.push(i);
     39             }
     40         }
     41     }
     42     return level[T]> 0 ? 1 : 0;
     43 }
     44 
     45 int dfs(int x, int f)
     46 {
     47     int a;
     48     if(x==T) return f;
     49     for(int i=0; i<=T; i++)
     50     {
     51         if(flow[x][i] && level[i]==level[x]+1 && (a=dfs(i,Min(f,flow[x][i]))))
     52         {
     53             flow[x][i] -= a;
     54             flow[i][x] += a;
     55             return a;
     56         }
     57     }
     58     level[x] = -1;
     59     return 0;
     60 }
     61 
     62 __int64 Dinic(int len)
     63 {       
     64     //    构建残余网络
     65     _clr(flow, 0);
     66     for(int i=1; i<=K; i++)
     67         flow[S][i] = M;
     68     for(int i=K+1; i<=ln; i++)
     69         flow[i][T] = 1;
     70     for(int i=1; i<=K; i++)   // 机器
     71         for(int j=K+1; j<=ln; j++)  // 奶牛
     72             flow[i][j] = (dist[i][j]<=len);
     73 
     74     //      求解最大流
     75     __int64 ans=0, a=0;
     76     while(bfs())
     77         while(a=dfs(0,INF)) ans += a;
     78     return ans;
     79 }
     80 
     81 //  二分求解满足条件的最小解
     82 int Slove()
     83 {
     84     int l=1, r=100000;
     85     while(l<=r)
     86     {
     87         int mid = (l+r)>>1;
     88         if(Dinic(mid)>=C) r = mid-1;
     89         else l = mid+1;
     90     }
     91     return l;
     92 }
     93 int main()
     94 {
     95     while(~scanf("%d%d%d", &K, &C, &M))
     96     {
     97         ln = K+C;
     98         T = ln + 1;
     99         _clr(dist, 0);
    100         for(int i=1; i<=ln; i++)
    101             for(int j=1; j<=ln; j++)
    102             {
    103                 scanf("%d", dist[i]+j);
    104                 if(dist[i][j]==0) dist[i][j]=INF;
    105             }
    106         //// 求出个实体之间的各个最短距离
    107         Floyd();
    108 
    109         printf("%d
    ", Slove());
    110     }
    111     return 0;
    112 }

  • 相关阅读:
    CSU 1333 Funny Car Racing
    FZU 2195 检查站点
    FZU 2193 So Hard
    ZOJ 1655 FZU 1125 Transport Goods
    zoj 2750 Idiomatic Phrases Game
    hdu 1874 畅通工程续
    hdu 2489 Minimal Ratio Tree
    hdu 3398 String
    洛谷 P2158 [SDOI2008]仪仗队 解题报告
    POJ 1958 Strange Towers of Hanoi 解题报告
  • 原文地址:https://www.cnblogs.com/khan724/p/4297843.html
Copyright © 2011-2022 走看看