Optimal Milking
FJ has moved his K (1 <= K <= 30) milking machines out into the cow pastures among the C (1 <= C <= 200) cows. A set of paths of various lengths runs among the cows and the milking machines. The milking machine locations are named by ID numbers 1..K; the cow locations are named by ID numbers K+1..K+C.
Each milking point can "process" at most M (1 <= M <= 15) cows each day.
Write a program to find an assignment for each cow to some milking machine so that the distance the furthest-walking cow travels is minimized (and, of course, the milking machines are not overutilized). At least one legal assignment is possible for all input data sets. Cows can traverse several paths on the way to their milking machine.
Input
* Line 1: A single line with three space-separated integers: K, C, and M.
* Lines 2.. ...: Each of these K+C lines of K+C space-separated integers describes the distances between pairs of various entities. The input forms a symmetric matrix. Line 2 tells the distances from milking machine 1 to each of the other entities; line 3 tells the distances from machine 2 to each of the other entities, and so on. Distances of entities directly connected by a path are positive integers no larger than 200. Entities not directly connected by a path have a distance of 0. The distance from an entity to itself (i.e., all numbers on the diagonal) is also given as 0. To keep the input lines of reasonable length, when K+C > 15, a row is broken into successive lines of 15 numbers and a potentially shorter line to finish up a row. Each new row begins on its own line.
Output
A single line with a single integer that is the minimum possible total distance for the furthest walking cow.
Sample Input
2 3 2
0 3 2 1 1
3 0 3 2 0
2 3 0 1 0
1 2 1 0 2
1 0 0 2 0
Sample Output
2
Source
题目类型:最大流
算法分析:这里将每天能够挤奶的奶牛数看作是网络流的最大流,建图时从源点向每个奶牛连一条容量为1的有向边,从每个挤奶器向汇点连一条容量为M的有向边,然后二分枚举最大路程maxv。若图中存在从某个奶牛到某个挤奶器的距离小于等于maxv,则在其之间连一条容量为1的有向边,最后依据求出的最大流的情况选择二分的方向
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 |
/************************************************* Author :supermaker Created Time :2016/3/26 8:32:32 File Location :C:\Users\abcd\Desktop\TheEternalPoet **************************************************/ #pragma comment(linker, "/STACK:102400000,102400000") #include <set> #include <bitset> #include <list> #include <map> #include <stack> #include <queue> #include <deque> #include <string> #include <vector> #include <ios> #include <iostream> #include <fstream> #include <sstream> #include <iomanip> #include <algorithm> #include <utility> #include <complex> #include <numeric> #include <functional> #include <cmath> #include <ctime> #include <climits> #include <cstdarg> #include <cstdio> #include <cstdlib> #include <cstring> #include <cctype> #include <cassert> using namespace std; #define CFF freopen ("aaa.txt", "r", stdin) #define CPPFF ifstream cin ("aaa.txt") #define DB(ccc) cout << #ccc << " = " << ccc << endl #define PB push_back #define MP(A, B) make_pair(A, B) typedef long long LL; typedef unsigned long long ULL; typedef double DB; typedef pair <int, int> PII; typedef pair <int, bool> PIB; const int INF = 0x7F7F7F7F; const int MOD = 1e9 + 7; const double EPS = 1e-10; const double PI = 2 * acos (0.0); const int maxn = 200 + 66; struct Node { int to, nxt, c, f; }; Node edge[maxn*maxn+maxn*3]; int head[maxn], edgelen; int dep[maxn], cnt[maxn], cur[maxn]; void Init () { memset (head, -1, sizeof (head)); memset (edge, -1, sizeof (edge)); edgelen = 0; } void AddEdge (int u, int v, int w, int rw = 0) { edge[edgelen].to = v, edge[edgelen].c = w, edge[edgelen].f = 0; edge[edgelen].nxt = head[u], head[u] = edgelen++; edge[edgelen].to = u, edge[edgelen].c = rw, edge[edgelen].f = 0; edge[edgelen].nxt = head[v], head[v] = edgelen++; } void bfs (int s, int e) { memset (dep, -1, sizeof (dep)); memset (cnt, 0, sizeof (cnt)); dep[e] = 0; cnt[dep[e]]++; queue <int> qu; qu.push (e); while (!qu.empty ()) { int u = qu.front (); qu.pop (); for (int i = head[u]; i != -1; i = edge[i].nxt) { int v = edge[i].to; if (dep[v] != -1) continue ; qu.push (v); dep[v] = dep[u] + 1; cnt[dep[v]]++; } } } int sta[maxn]; int MaxFlow (int s, int e, int n) { bfs (s, e); int res = 0, top = 0, u = s; memcpy (cur, head, sizeof (head)); while (dep[s] < n) { if (u == e) { int minval = INF, minval_pos = -1; for (int i = 0; i < top; i++) if (minval > edge[sta[i]].c - edge[sta[i]].f) { minval = edge[sta[i]].c - edge[sta[i]].f; minval_pos = i; } for (int i = 0; i < top; i++) { edge[sta[i]].f += minval; edge[sta[i]^1].f -= minval; } res += minval; top = minval_pos; u = edge[sta[top]^1].to; } else { bool is_have = false; for (int i = cur[u]; i != -1; i = edge[i].nxt) { int v = edge[i].to; if (edge[i].c - edge[i].f && dep[v] + 1 == dep[u]) { cur[u] = i; sta[top++] = cur[u]; u = v; is_have = true; break; } } if (is_have) continue ; int minval = n; for (int i = head[u]; i != -1; i = edge[i].nxt) if (edge[i].c - edge[i].f && dep[edge[i].to] < minval) { minval = dep[edge[i].to]; cur[u] = i; } cnt[dep[u]]--; if (!cnt[dep[u]]) return res; dep[u] = minval + 1; cnt[dep[u]]++; if (u != s) u = edge[sta[--top]^1].to; } } return res; } int g[maxn][maxn], dis[maxn][maxn], K, C, M; void floyd () { for (int i = 1; i <= K + C; i++) for (int j = 1; j <= K + C; j++) { if (g[i][j]) dis[i][j] = g[i][j]; else if (i == j) dis[i][j] = 0; else dis[i][j] = INF; } for (int k = 1; k <= K + C; k++) for (int i = 1; i <= K + C; i++) for (int j = 1; j <= K + C; j++) { if (i == k || j == k) continue ; if (dis[i][k] < INF && dis[k][j] < INF) dis[i][j] = min (dis[i][j], dis[i][k] + dis[k][j]); } } void SS (int maxv) { Init (); for (int i = K + 1; i <= K + C; i++) AddEdge (K + C + 1, i, 1); for (int i = 1; i <= K; i++) AddEdge (i, 0, M); for (int i = K + 1; i <= K + C; i++) for (int j = 1; j <= K; j++) if (dis[i][j] <= maxv) AddEdge (i, j, 1); } int main() { //CFF; //CPPFF; while (scanf ("%d%d%d", &K, &C, &M) != EOF) { for (int i = 1; i <= K + C; i++) for (int j = 1; j <= K + C; j++) scanf ("%d", &g[i][j]); floyd (); int low = 0, high = 100000, mid; while (low <= high) { mid = (low + high) >> 1; SS (mid); int res = MaxFlow (K + C + 1, 0, K + C + 2); if (res >= C) high = mid - 1; else low = mid + 1; } printf ("%d\n", low); } return 0; } |
- « 上一篇:poj2337
- poj1087:下一篇 »