题目大意是:
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 }