| ||||||||||
| Online Judge | Problem Set | Authors | Online Contests | User | ||||||
|---|---|---|---|---|---|---|---|---|---|---|
| Web Board Home Page F.A.Qs Statistical Charts | Current Contest Past Contests Scheduled Contests Award Contest | |||||||||
二分答案+网络流判断可行性,附AC代码前辈有句话总结的好——最大值最小,最小值最大,十有八九是二分。Orz
那显然这题就是二分答案喽!
首先,枚举的下界就是1喽!为什么不会是0嘞?因为0在输入中代表的是没有边哦。
其次,枚举的上界就是Floyd之后的最大值喽!好麻烦啊,那就用200*(K+C)凑合一下吧。
然后,枚举了mid,怎么判断是否可行呢?
我们找来了网络流兄弟,请他帮帮忙吧。
对于原图,如果两点间距离>mid,那么这条路径就是不能走的;反之,就是能走的。
于是,对于一个枚举的mid,利用所有长度<=mid的路径构造网络流图,跑最大流。
具体构造方法:
超级源点向每个机器连一条容量为M的边,超级汇点向每只哞哞连一条容量为1的边。
然后,每个机器和每只哞哞之间,如果距离<=mid,就连一条容量为1的边。
如果最大流==牛的总数,那么就是可行的。
题意保证存在解使得所有哞哞都有机器,即 C<=K*M。
那么,上好的代码来了!
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
/* POJ 2112 */
const int INF = 0x3f3f3f3f;
const int maxK = 35, maxC = 205, maxM = 20, maxV = 300;
int K, C, M, V;
int G[maxV][maxV];
int cap[maxV][maxV], dep[maxV], St, Ed;
inline void buildGraph(int limit) {
/* prepare */
memset(cap, 0, sizeof(cap));
St = 0, Ed = V + 1;
/* milkingMachines */
for (int i = 1; i <= K; i++)
cap[St][i] += M;
/* cows */
for (int i = K + 1; i <= V; i++)
cap[i][Ed] += 1;
/* cows and milingMachines */
for (int i = 1; i <= K; i++)
for (int j = K + 1; j <= V; j++)
cap[i][j] += (G[i][j] <= limit);
}
inline bool dinicBFS(void) {
/* prepare for BFS */
memset(dep, -1, sizeof(dep));
int que[maxV], head = 0, tail = 0;
/* start of BFS */
que[tail++] = St, dep[St] = 0;
while (head != tail) {
int u = que[head++];
for (int v = 0; v <= Ed; v++)
if (dep[v] == -1 && cap[u][v])
dep[v] = dep[u] + 1, que[tail++] = v;
}
return dep[Ed] != -1;
}
inline int dinicDFS(int u, int f) {
if (u == Ed)return f;
int tmp = f, newFlow;
for(int v=0;v<=Ed;v++)
if (dep[v] == dep[u] + 1 && cap[u][v] > 0) {
newFlow = dinicDFS(v, min(tmp, cap[u][v]));
cap[u][v] -= newFlow;
cap[v][u] += newFlow;
tmp -= newFlow;
}
return f - tmp;
}
inline int dinic(void) {
/* maxFlow */
int maxFlow = 0;
while (dinicBFS())
maxFlow += dinicDFS(St, INF);
return maxFlow;
}
inline bool check(int mid) {
buildGraph(mid);
int maxFlow = dinic();
return maxFlow == C;
}
inline void Floyd(void) {
/* FloydAlgorithm */
for (int k = 1; k <= V; k++)
for (int i = 1; i <= V; i++)
for (int j = 1; j <= V; j++)
G[i][j] = min(G[i][j], G[i][k] + G[k][j]);
}
signed main(void) {
#ifndef ONLINE_JUDGE
printf(" POJ 2112 \n By YOUSIKI \n");
#endif
/* input */
scanf("%d%d%d", &K, &C, &M), V = K + C;
for (int i = 1; i <= V; i++)
for (int j = 1; j <= V; j++)
scanf("%d", &G[i][j]);
for (int i = 1; i <= V; i++)
for (int j = 1; j <= V; j++)
if (G[i][j] == 0)G[i][j] = INF;
Floyd();
/* binarySearch */
int left = 1, right = V * 200, mid, ans = 1;
while (left <= right) {
mid = (left + right) >> 1;
if (check(mid))right = mid - 1, ans = mid;
else left = mid + 1;
}
/* output */
printf("%d\n", ans);
#ifndef ONLINE_JUDGE
system("pause");
#endif
} // By YOUSIKI
Followed by: Post your reply here: |
All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator