POJ2112 Optimal Milking 【最大流+二分】

Optimal Milking

Time Limit: 2000MS   Memory Limit: 30000K
Total Submissions: 12482   Accepted: 4508
Case Time Limit: 1000MS

Description

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

USACO 2003 U S Open

题意:有k台挤奶器,每台挤奶器最多容纳m头奶牛,该牧场共有c头奶牛,现在给定这k台机器和c头奶牛相互间的直接距离,求让所有奶牛到达挤奶器且满足该条件时奶牛走到挤奶器间的最大距离的最小值。

题解:构图:先用Floyd求出相互间的最短距离,然后设置源点到每头牛的距离为1,每台机器到汇点的距离为m,然后若牛到机器的距离不大于maxdist,那么则将该边加入到新图中,最后对新图求最大流,判断最大流是否等于c,就这样二分枚举maxdist直到找到最小的maxdist为止。

#include <stdio.h>
#include <string.h>
#define inf 0x3fffffff
#define maxn 235

int dist[maxn][maxn], k, c, m, n;
int G[maxn][maxn], Layer[maxn];
int queue[maxn], maxDist;
bool vis[maxn];

void Floyd() {
    int x, i, j;
    maxDist = 200;
    for(x = 1; x <= n; ++x)
        for(i = 1; i <= n; ++i)
            for(j = 1; j <= n; ++j)
                if(dist[i][j] > dist[i][x] + dist[x][j]) {
                    dist[i][j] = dist[i][x] + dist[x][j];
                    if(maxDist < dist[i][j]) maxDist = dist[i][j];
                }
}

void build(int flow) {
    memset(G, 0, sizeof(G));
    int i, j;
    for(i = k + 1; i <= n; ++i) {
        G[0][i] = 1;
        for(j = 1; j <= k; ++j)
            if(dist[i][j] <= flow)
                G[i][j] = 1;
    }
    for(j = 1; j <= k; ++j)
        G[j][n + 1] = m;
}

bool countLayer() {
    int id = 0, front = 0, now, i;
    memset(Layer, 0, sizeof(Layer));
    Layer[0] = 1; queue[id++] = 0;
    while(front < id) {
        now = queue[front++];
        for(i = 0; i <= n + 1; ++i)
            if(G[now][i] && !Layer[i]) {
                Layer[i] = Layer[now] + 1;
                if(i == n + 1) return true;
                else queue[id++] = i;
            }
    }
    return false;
}

bool Dinic() {
    int i, maxFlow = 0, id = 0, now, minCut, pos, u, v;
    while(countLayer()) {
        memset(vis, 0, sizeof(vis));
        vis[0] = 1; queue[id++] = 0;
        while(id) {
            now = queue[id - 1];
            if(now == n + 1) {
                minCut = inf;
                for(i = 1; i < id; ++i) {
                    u = queue[i - 1];
                    v = queue[i];
                    if(G[u][v] < minCut) {
                        minCut = G[u][v];
                        pos = u;
                    }
                }
                maxFlow += minCut;
                for(i = 1; i < id; ++i) {
                    u = queue[i - 1];
                    v = queue[i];
                    G[u][v] -= minCut;
                    G[v][u] += minCut;
                }
                while(id && queue[id - 1] != pos)
                    vis[queue[--id]] = 0;
            } else {
                for(i = 0; i <= n + 1; ++i) {
                    if(G[now][i] && !vis[i] && Layer[now] + 1 == Layer[i]) {
                        queue[id++] = i;
                        vis[i] = 1; break;
                    }
                }
                if(i > n + 1) --id;
            }
        }
    }
    return maxFlow == c;
}

int binarySolve() {
    int left = 0, right = maxDist, mid;
    while(left < right) {
        mid = (left + right) >> 1;
        build(mid);
        if(Dinic()) right = mid;
        else left = mid + 1;
    }
    return left;
}

int main() {
    //freopen("stdin.txt", "r", stdin);
    int i, j;
    while(scanf("%d%d%d", &k, &c, &m) == 3) {
        for(i = 1, n = k + c; i <= n; ++i)
            for(j = 1; j <= n; ++j) {
                scanf("%d", &dist[i][j]);
                if(!dist[i][j] && i != j)
                    dist[i][j] = inf;
            }
        Floyd();
        printf("%d\n", binarySolve());
    }
    return 0;
}
时间: 2024-08-04 22:32:53

POJ2112 Optimal Milking 【最大流+二分】的相关文章

poj2112 Optimal Milking --- 最大流,二分

nx个挤奶器,ny头奶牛,每个挤奶器最多能供m头奶牛使用. 现给出nx+ny之间的距离矩阵,求使得全部奶牛都到某个挤奶器挤奶所走的路程中,单个奶牛所走的最大路程的最小值. 开始感觉这个类似二分图匹配,不同之处在于挤奶器可以连接m个以内的奶牛,用网络流的模型是可以求出满足条件的解的. 问题是如何满足最大路程的最小值,这一种典型的二分的问法.. 所以我们二分答案,也就是枚举最大路程,直到求得最小值. 每次建边既添加所有最大路程以内的边,添加源点向每个挤奶器建边,容量为m,其他边都是1, 若返回的最大

POJ-2112 Optimal Milking(最大流)未完待续~

1 #include <cstdio> 2 #include <cmath> 3 #include <cstdlib> 4 #include <cstring> 5 #include <queue> 6 #include <stack> 7 #include <vector> 8 #include <iostream> 9 #include "algorithm" 10 #define me

POJ2112 Optimal Milking 二分法+网络流

题目大意是:K台挤奶机器,C头牛,K不超过30,C不超过200,每台挤奶机器最多可以为M台牛工作,给出这些牛和机器之间,牛和牛之间,机器与机器之间的距离,在保证让最多的牛都有机器挤奶的情况下,给出其中最长的一头牛移动的距离的最小值. 首先用Floyd求出任意两点之间的最短距离,然后再用二分法限定最多的移动距离d,在求最大流时,搜索增广路的时候同时也判断距离有没有超过d就行了. #include <stdlib.h> #include <stdio.h> #include <v

POJ-2112 Optimal Milking(floyd+最大流+二分)

题目大意: 有k个挤奶器,在牧场里有c头奶牛,每个挤奶器可以满足m个奶牛,奶牛和挤奶器都可以看成是实体,现在给出两个实体之间的距离,如果没有路径相连,则为0,现在问你在所有方案里面,这c头奶牛需要走的最大距离的最小值. 分析: 先将题目给出来的距离矩阵跑一下 Floyd 求出全源最短路方便后面建图, 这里注意一下除了对角线的点若有其他点为 0 则应将其值设置为 INF 代表不可达 在使用最大流判断是否存在解的时候,要对每个解都重新建图. 建图需要一个超级源点,把所有的奶牛与源点相连,容量设置为1

POJ2112 Optimal Milking(最大流)

先Floyd求牛到机器最短距离,然后二分枚举最长的边. 1 #include<cstdio> 2 #include<cstring> 3 #include<queue> 4 #include<algorithm> 5 using namespace std; 6 #define INF (1<<30) 7 #define MAXN 233 8 #define MAXM 233*233*20 9 10 struct Edge{ 11 int v,c

poj 2112 Optimal Milking 最大流

http://poj.org/problem?id=2112 [题意]  k个机器,每个机器最多服务m头牛.c头牛,每个牛需要1台机器来服务.给出一个矩阵表示每两个实体之间的直接距离.(注意两个实体没有直接 距离的时候用0表示) 问:让所有的牛都被服务的情况下,使走的最远的牛的距离最短,求这个距离. [思路]  先用floyd求出每两个实体间的最短距离,再二分所求的距离len. [建图] 源点向每个机器连边,容量为m.每个机器向距离小于len的牛连边,容量为1.每头牛向汇点连边,容量为1.若最大

(二分最大流) 最大流 + 二分查找 小结

做最大流题目的时候会遇到一种需要用二分查找的题型: (poj2455) 一张无向图中有 N 个点,M 条边,每条边都有一个权值,且每条边只能用一次,要求找出 T 条从 1 到 N 的路径,使这 T 条路径所经过的边中,权值的最大值最小. 转化为最大流模型:T就是最大流,每条边只能用一次在网络流中就是容量为1.然后二分查找(枚举),边权小于或等于mid的边就加一条容量为1的网络流的边.最后知道最大流ans与T相等的最小的mid就是所求. 在二分查找的时候,与一般的二分查找还是有区别的,一般不能有“

POJ 2112 Optimal Milking(二分+最大流)

POJ 2112 Optimal Milking 题目链接 题意:给定一些机器和奶牛,在给定距离矩阵,(不在对角线上为0的值代表不可达),每个机器能容纳m个奶牛,问所有奶牛都能挤上奶,那么走的距离最大的奶牛的最小值是多少 思路:明显的二分+最大流,注意floyd求出的距离矩阵最大值可能不止200,所以二分的上限要注意 代码: #include <cstdio> #include <cstring> #include <queue> #include <algori

POJ 2112 Optimal Milking 最优挤奶方案 Floyd算法+二分查找+最大流

题目链接:POJ 2112 Optimal Milking Optimal Milking Time Limit: 2000MS   Memory Limit: 30000K Total Submissions: 12446   Accepted: 4494 Case Time Limit: 1000MS Description FJ has moved his K (1 <= K <= 30) milking machines out into the cow pastures among