POJ_2112 Optimal Milking(网络流)

  /*昨晚写把Dinic写错了,一直不出结果,也没调出来,睡觉之前猛然想起来,少了
一个break,造成死循环了。今天把那地方改过来,交上去WA。然后又重新敲之,TLE。
后来检查了一遍,发现是Floyd写错了,改过后终于过了,发现网络流太容易错了。

  思路:

1、用Floyd把每个奶牛到每个挤奶机的距离算出来,然后问题就变成了已知c头奶牛到
k个挤奶机的距离,求走最远距离的牛走的路程mindis最小是多少。

2、然后建网络流模型,每头奶牛和挤奶机都是一个结点。设一个源点s,s到c头奶牛
的容量都记为1,k个挤奶机到汇点T的距离都记为m。

3、先假设一个mindis的值,然后当奶牛到挤奶机的距离小于mindis时,奶牛结点到挤
奶机结点的容量为1。

4、用一次Dinic()求出最大流,如果 Dinic() == c,mindis减小重复3步骤,直到找
到最小距离。


My Code:
*/

#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>

using namespace std;

const int N = 300;
const int inf = 0x6fffffff;

int map[N][N];
int g[N][N];
int layer[N];
bool vis[N];
int T, n;

bool Layer() {
int i, v;
deque<int> q;
memset(layer, -1, sizeof(layer));
q.push_back(0);
layer[0] = 0;
while(!q.empty()){
v = q.front();
q.pop_front();
for(i = 0; i <= T; i++) {
if(g[v][i] > 0 && layer[i] == -1) {
layer[i] = layer[v] + 1;
if(i == T) {q.clear(); return true;}
else q.push_back(i);
}
}
}
return false;
}

int Dinic() {

deque<int> q;
int v, i, vs, ve, min, min_s, sum = 0;
while(Layer()) {
memset(vis, false, sizeof(vis));
vis[0] = true;
q.push_back(0);
while(!q.empty()) {
v = q.back();
if(v == T) {
min = inf;
for(i = 1; i < q.size(); i++) {
vs = q[i-1]; ve = q[i];
if(g[vs][ve] > 0 && min > g[vs][ve]) {
min = g[vs][ve];
min_s = vs;
}
}
sum += min;
for(i = 1; i < q.size(); i++) {
vs = q[i-1]; ve = q[i];
if(g[vs][ve] > 0) {
g[vs][ve] -= min;
g[ve][vs] += min;
}
}
while(!q.empty() && q.back() != min_s) {
vis[q.back()] = false;
q.pop_back();
}
} else {
for(i = 0; i <= T; i++) {
if(g[v][i] > 0 && !vis[i] && layer[i] == layer[v] + 1) {
vis[i] = true;
q.push_back(i);
break;
}
}
if(i > T) q.pop_back();
}
}
}
return sum;
}

void built(int dis, int k, int m) {
int i, j;
memset(g, 0, sizeof(g));
for(i = k+1; i <= n; i++) {
g[0][i] = 1;
for(j = 1; j <= k; j++) {
if(map[i][j] <= dis) g[i][j] = 1;
}
}
for(i = 1; i <= k; i++) {
g[i][T] = m;
}
}

void Floyd() {
int i, j, k;
for(k = 1; k <= n; k++) {
for(i = 1; i <= n; i++) {
for(j = 1; j <= n; j++) {
if(i != j && map[i][k] != inf && map[k][j] != inf && map[i][k] + map[k][j] < map[i][j]){
map[i][j] = map[i][k] + map[k][j];
}
}
}
}
}

int main() {
//freopen("data.in", "r", stdin);

int k, c, m, i, j, ans;
int l, r, mid;

scanf("%d%d%d", &k, &c, &m);{
n = k + c; T = n + 1;
memset(map, 0, sizeof(map));

for(i = 1; i <= n; i++) {
for(j = 1; j <= n; j++) {
scanf("%d", &map[i][j]);
if(map[i][j] == 0) map[i][j] = inf;
}
}
Floyd();
l = 0, r = inf - 10;
while(l < r) {
mid = (l + r) >> 1;

built(mid, k, m);
ans = Dinic();
//printf("%d %d\n", ans, mid);
if(ans == c) r = mid;
else l = mid + 1;
}
printf("%d\n", r);
}
return 0;
}

你可能感兴趣的:(poj)