题意:
有C头奶牛和K台挤奶机,已知每台挤奶机只能给M头牛挤奶。奶牛编号从K+1 到 K+C,挤奶机编号从1 到 K。现在给你一个 (K + C) * (K + C)的矩阵,矩阵第 i 行 第 j 列 的元素代表第i个点到第j个点的距离。求给每头奶牛挤奶的,使得C头奶牛需要行走的路程中的最大路程的最小值。
思路:
Floyd求每头奶牛到挤奶机的最小距离,二分答案,每次 check 对于距离小于 mid 的 i ,j 建边,判断最大流是否等于奶牛数。
代码:
1 //#include<bits/stdc++.h>
2 #include <set>
3 #include <map>
4 #include <stack>
5 #include <cmath>
6 #include <queue>
7 #include <cstdio>
8 #include <string>
9 #include <vector>
10 #include <cstring>
11 #include <iostream>
12 #include <algorithm>
13
14 #define ll long long
15 #define pll pair<ll,ll>
16 #define pii pair<int,int>
17 #define bug printf("*********
")
18 #define FIN freopen("input.txt","r",stdin);
19 #define FON freopen("output.txt","w+",stdout);
20 #define IO ios::sync_with_stdio(false),cin.tie(0)
21 #define ls root<<1
22 #define rs root<<1|1
23 #define Q(a) cout<<a<<endl
24
25 using namespace std;
26 const int inf = 0x3f3f3f3f;
27 const ll Inf = 1e18 + 7;
28 const int maxn = 1e5 + 5;
29 const int mod = 1e9 + 7;
30
31 ll gcd(ll a, ll b)
32 {
33 return b ? gcd(b, a % b) : a;
34 }
35
36 ll lcm(ll a, ll b)
37 {
38 return a / gcd(a, b) * b;
39 }
40
41 ll read()
42 {
43 ll p = 0, sum = 0;
44 char ch;
45 ch = getchar();
46 while (1)
47 {
48 if (ch == '-' || (ch >= '0' && ch <= '9'))
49 break;
50 ch = getchar();
51 }
52
53 if (ch == '-')
54 {
55 p = 1;
56 ch = getchar();
57 }
58 while (ch >= '0' && ch <= '9')
59 {
60 sum = sum * 10 + ch - '0';
61 ch = getchar();
62 }
63 return p ? -sum : sum;
64 }
65
66 struct Dinic
67 {
68 int head[maxn], tot, cur[maxn];
69 int dis[maxn];
70 int s, e;
71 queue<int>q;
72
73 struct node
74 {
75 int v, w;
76 int next;
77 }p[maxn];
78
79 void init()
80 {
81 tot = 0;
82 memset(head, -1, sizeof head);
83 }
84
85 void add(int u, int v, int w)
86 {
87 p[tot].v = v;
88 p[tot].w = w;
89 p[tot].next = head[u];
90 head[u] = tot++;
91 }
92
93 void addEdge(int u, int v, int w)
94 {
95 add(u, v, w);
96 add(v, u, 0);
97 }
98
99 bool bfs()
100 {
101 memset(dis, 0, sizeof dis);
102 while (!q.empty()) q.pop();
103 dis[s] = 1;
104 q.push(s);
105 while (!q.empty())
106 {
107 int x = q.front();
108 q.pop();
109 for (int i = head[x]; i != -1; i = p[i].next)
110 {
111 int v = p[i].v, w = p[i].w;
112 if (!dis[v] && w)
113 {
114 dis[v] = dis[x] + 1;
115 q.push(v);
116 }
117 }
118 }
119 if (dis[e]) return true;
120 return false;
121 }
122
123 int dfs(int x, int W)
124 {
125 if (x == e || W == 0) return W;
126 int res = 0;
127 for (int i = cur[x]; i != -1; i = p[i].next)
128 {
129 cur[x] = p[i].next;
130 int v = p[i].v, w = p[i].w;
131 if (dis[v] == dis[x] + 1)
132 {
133 int f = dfs(v, min(w, W));
134 p[i].w -= f;
135 p[i ^ 1].w += f;
136 W -= f;
137 res += f;
138 if (W == 0) break;
139 }
140 }
141 return res;
142 }
143
144 int getMaxFlow()
145 {
146 int ans = 0;
147 while (bfs())
148 {
149 for (int i = s; i <= e; ++i) cur[i] = head[i];
150 ans += dfs(s, inf);
151 }
152 return ans;
153 }
154 }DC;
155
156 struct stortest_Floyd {
157 int a[5000][5000];
158 void floyd(int num) {
159 for (int k = 1; k <= num; k++) {
160 for (int i = 1; i <= num; i++) {
161 for (int j = 1; j <= num; j++) {
162 if (a[i][j] > a[i][k] + a[k][j]) {
163 a[i][j] = a[i][k] + a[k][j];
164 }
165 }
166 }
167 }
168 }
169 }Floyd;
170
171 int k, c, m;
172 int num;
173
174 void add(int x)
175 {
176 for (int i = 1; i <= k; ++i)
177 {
178 for (int j = k + 1; j <= num; ++j)
179 {
180 if (Floyd.a[i][j] <= x)
181 DC.addEdge(j, i, 1);
182 }
183 }
184 for (int i = 1; i <= k; ++i)
185 {
186 DC.addEdge(i, DC.e, m);
187 }
188 for (int i = k + 1; i <= num; ++i)
189 {
190 DC.addEdge(DC.s, i, 1);
191 }
192 }
193
194 int main()
195 {
196 while (~scanf("%d %d %d", &k, &c, &m))
197 {
198 num = k + c;
199 DC.s = 0, DC.e = num + 1;
200 int nv = num + 2;
201
202 for (int i = 1; i <= num; ++i)
203 {
204 for (int j = 1; j <= num; ++j)
205 {
206 scanf("%d", &Floyd.a[i][j]);
207 if (i != j && !Floyd.a[i][j])
208 {
209 Floyd.a[i][j] = inf;
210 }
211 }
212 }
213 Floyd.floyd(num);
214
215 int l = 0, r = inf;
216 int ans = 0;
217 while (l <= r)
218 {
219 int mid = (l + r) / 2;
220 DC.init();
221 add(mid);
222 int res = DC.getMaxFlow();
223 if (res == c)
224 {
225 ans = mid;
226 r = mid - 1;
227 }
228 else l = mid + 1;
229 }
230 printf("%d
", ans);
231 }
232 }