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\n", Slove());

110     }

111     return 0;

112 }

 

你可能感兴趣的:(dinic)