题意:K个产奶机,C头奶牛,每个产奶机最多可供M头奶牛使用;并告诉了产奶机、奶牛之间的两两距离Dij(0<=i,j<K+C)。
问题:如何安排使得在任何一头奶牛都有自己产奶机的条件下,奶牛到产奶机的最远距离最短?最短是多少?
二分答案。
注意先floyd求得两两之间最小距离,二分的时候上界不是200。200只是直接相连的最大距离。
1 // File Name: 2112.cpp 2 // Author: Missa 3 // Created Time: 2013/4/11 星期四 14:20:52 4 5 #include<iostream> 6 #include<cstdio> 7 #include<cstring> 8 #include<algorithm> 9 #include<cmath> 10 #include<queue> 11 #include<stack> 12 #include<string> 13 #include<vector> 14 #include<cstdlib> 15 #include<map> 16 #include<set> 17 using namespace std; 18 #define CL(x,v) memset(x,v,sizeof(x)); 19 #define R(i,st,en) for(int i=st;i<en;++i) 20 #define LL long long 21 #define inf 0x3f3f3f3f 22 int a[240][240]; 23 int K,C,M; 24 25 const int maxn = 240; 26 int cap[maxn][maxn]; 27 int lev[maxn]; 28 int n, m; 29 int st, en; 30 31 bool bfs() 32 { 33 queue <int> q; 34 while (!q.empty()) q.pop(); 35 memset(lev, -1, sizeof(lev)); 36 lev[st] = 0; 37 q.push(st); 38 while (!q.empty()) 39 { 40 int u = q.front();q.pop(); 41 for (int v = 0; v <= n+1; ++v) 42 if (lev[v] == -1 && cap[u][v] != 0) 43 { 44 lev[v] = lev[u] + 1; 45 q.push(v); 46 } 47 } 48 return lev[en] != -1; 49 } 50 int dfs(int u, int cur_flow) 51 { 52 int dt = cur_flow; 53 if (u == en) return dt; 54 for (int v = 0; v <= n + 1; ++v) 55 { 56 if (cap[u][v] > 0 && lev[u] + 1 == lev[v]) 57 { 58 int flow = dfs(v, min(dt, cap[u][v])); 59 cap[u][v] -= flow; 60 cap[v][u] += flow; 61 dt -= flow; 62 } 63 } 64 return cur_flow - dt; 65 } 66 67 int dinic() 68 { 69 int cur_flow, ans = 0; 70 while(bfs()) 71 while(cur_flow = dfs(st, inf)) 72 ans += cur_flow; 73 return ans; 74 } 75 void build(int dis) 76 { 77 memset(cap, 0, sizeof(cap)); 78 n = K + C; 79 st = 0; 80 en = n + 1; 81 for (int i = 1; i <= K; ++i) 82 cap[0][i] += M; 83 for (int i = K + 1; i <= K + C; ++i) 84 cap[i][en] += 1; 85 for (int i = 1; i <= K; ++i) 86 for (int j = K + 1; j <= K + C; ++j) 87 if (a[i][j] <= dis) 88 cap[i][j] += 1; 89 } 90 91 92 int main() 93 { 94 while(~scanf("%d%d%d",&K, &C, &M)) 95 { 96 for (int i = 1; i <= K + C; ++i) 97 for (int j = 1; j <= K + C; ++j) 98 { 99 scanf("%d", &a[i][j]); 100 if (a[i][j] == 0) a[i][j] = inf; 101 } 102 for (int k = 1; k <= K + C; ++k) 103 for (int i = 1; i <= K + C; ++i) 104 for (int j = 1; j <= K + C; ++j) 105 a[i][j]= min(a[i][j],a[i][k]+a[k][j]); 106 /*for (int i = 1; i <= K + C; ++i) 107 { 108 for (int j = 1; j <= K + C; ++j) 109 cout<<a[i][j]<<" "; 110 cout<<endl; 111 }*/ 112 int ans = 1, low = 1, high = inf; 113 while(low <= high) 114 { 115 int mid = (low + high) >> 1; 116 build(mid); 117 if (dinic() == C) 118 { 119 ans = mid; 120 high = mid - 1; 121 } 122 else 123 low = mid + 1; 124 } 125 printf("%d\n", ans); 126 127 } 128 return 0; 129 }