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 }

  • 相关阅读:
    只能输入数字的文本框
    Ajax
    Crtl+Enter提交留言
    onkeydown onkeyup键盘事件
    面向对象基础
    JS鼠标拖拽
    博客收藏
    不错的按钮
    如何在你的java程序中注册系统级热键
    开源GIS系统
  • 原文地址:https://www.cnblogs.com/khan724/p/4297843.html
Copyright © 2011-2022 走看看