POJ 2112 最大流+二分+(建图:最重要的)

Optimal Milking

Time Limit: 2000MS   Memory Limit: 30000K
Total Submissions: 12521   Accepted: 4524
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

题目意思:有K个牛奶站(1--K),C个牛(K+1---C),牛和牛、牛和牛奶站、牛奶站和牛奶站之间有些边,所有的牛都需要到牛奶站,牛奶站最多容纳M个牛,求在满足题目条件下,所有的牛都到牛奶站所经过的最大路程中最小的。

思路:假设输入的图如下:

其中圆代表牛,方块代表牛奶站。

易知若使得最大路程最小,那么该路径必须在某头牛与某个牛奶站之间的最短距离。

那么经过floyd求的牛与牛奶站之间的最短距离后,图如下:

此时图示路径都是最短路径,最大路径就在这些路径当中(设这些路径中最大为maxh),那么怎么找出来呢,就想到了对这些边二分查找(查找区间为[0,maxh],查找的边为最大边),当查找到的这条最大边处于不超过所有牛奶站容量和超过某些牛奶站容量临界状态下,那么满足所有牛奶站容量的边即为答案。

那么又怎么判断当这条边为最大边时牛奶站容量是否超过最大容量呢?那么就有最大流了,虚拟一个源点,使得源点指向牛,虚拟一个汇点,使得牛奶站指向汇点,建图如下:

其中红线为查找到的最大边,在第二边集中其他的边均小于红线。第一边集和第二边集边的容量为1,第三边集边的容量为M。

求的源点0到汇点8的最大流若为牛个数C的话说明不超过牛奶站容量。

经过上面分析就知道实现过程了:

先对输入的图进行floyd求最短路径,然后找出牛和牛奶站之间最大边maxh,从[0,maxh]中二分查找最大边,根据这个最大边从新建图,然后用最大流判断这条边是否满足不超过牛奶站容量的条件。

代码:

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4 #include <iostream>
  5 #include <vector>
  6 #include <queue>
  7 using namespace std;
  8
  9 #define inf 9999999
 10
 11 vector<int>ve[6100];
 12 int map[240][240];
 13 int g[240][240];
 14 int flow[240], father[240];
 15 int K, C, M;
 16
 17 int build(int lim){        //建图,新图为g[][]
 18     int i, j, k, maxh=-1;
 19     memset(g,0,sizeof(g));
 20     for(i=K+1;i<=K+C;i++) g[0][i]=1;
 21     for(i=1;i<=K;i++) g[i][K+C+1]=M;
 22     for(i=K+1;i<=K+C;i++){
 23         for(j=1;j<=K;j++){
 24             if(map[i][j]<=lim){
 25                 g[i][j]=1;
 26                 maxh=max(maxh,map[i][j]);
 27             }
 28
 29         }
 30     }
 31     return maxh;
 32 }
 33
 34 int bfs(){                     //找增广路
 35     int i, j, u, v;
 36     queue<int>Q;
 37     while(!Q.empty()) Q.pop();
 38     u=0;
 39     memset(father,-1,sizeof(father));
 40     flow[u]=inf;
 41     father[u]=0;
 42     Q.push(u);
 43     while(!Q.empty()){
 44         u=Q.front();Q.pop();
 45         for(v=1;v<=K+C+1;v++){
 46             if(father[v]==-1&&g[u][v]>0){
 47                 flow[v]=min(flow[u],g[u][v]);
 48                 father[v]=u;
 49                 Q.push(v);
 50             }
 51         }
 52     }
 53     if(father[K+C+1]==-1) return -1;
 54     return flow[K+C+1];
 55 }
 56
 57 int FLOW(){                 //最大流
 58     int i, j, step;
 59     int ans=0;
 60     while((step=bfs())!=-1){
 61         ans+=step;
 62         int u=K+C+1;
 63         while(u!=0){
 64             g[father[u]][u]-=step;
 65             g[u][father[u]]+=step;
 66             u=father[u];
 67         }
 68     }
 69     return ans;
 70 }
 71
 72 main()
 73 {
 74     int i, j, k;
 75     while(scanf("%d %d %d",&K,&C,&M)==3){
 76         for(i=1;i<=K+C;i++){
 77             for(j=1;j<=K+C;j++){
 78                 scanf("%d",&map[i][j]);
 79                 if(!map[i][j]) map[i][j]=inf;
 80             }
 81         }
 82         int minmax=-1;
 83         for(k=1;k<=K+C;k++){              //floyd最短路径
 84             for(i=1;i<=K+C;i++){
 85                 for(j=1;j<=K+C;j++){
 86                     map[i][j]=min(map[i][j],map[i][k]+map[k][j]);
 87                     if(map[i][j]<inf) minmax=max(minmax,map[i][j]);
 88                 }
 89             }
 90         }
 91         int l=0, r=minmax, ans;
 92         while(l<r){                    //二分查找
 93             int mid=(l+r)/2;
 94             build(mid);              //根据查找到的最大边mid从新建图
 95             if(FLOW()>=C) r=mid;        //最大流判断是否满足不超过牛奶站容量的条件
 96             else l=mid+1;
 97         }
 98         ans=build(r);                 //查找的mid仅为最大边的上届,不一定是最大边,所以找最接近上届的边即为最大边
 99         printf("%d\n",ans);
100     }
101 }
时间: 2024-12-24 13:46:11

POJ 2112 最大流+二分+(建图:最重要的)的相关文章

poj 2226 Muddy Fields(合理建图+二分匹配)

1 /* 2 题意:用木板盖住泥泞的地方,不能盖住草.木板任意长!可以重叠覆盖! '*'表示泥泞的地方,'.'表示草! 3 思路: 4 首先让我们回忆一下HDU 2119 Matrix这一道题,一个矩阵中只有0, 1,然后让我们通过选择一行,或者 5 是一列将其所在行的或者所在列的 1全部删掉,求出最少需要几步? 6 7 这道题的思路就是:将行标 和 列标值为1的建立一条边!通过匈牙利算法可以得到这个二分图的最大匹配数 8 最大匹配数==最小顶点覆盖数!最小顶点覆盖就是用最少的点覆盖了这个二分图

POJ 2112 Optimal Milking 二分答案+最大流

首先二分最长的边,然后删去所有比当前枚举的值长的边,算最大流,看是否能满足所有的牛都能找到挤奶的地方 #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <climits> #include <string> #include <iostream> #include <map> #include

HDU 3376--Matrix Again【最大费用最大流 &amp;&amp; 经典建图】

Matrix Again Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 102400/102400 K (Java/Others) Total Submission(s): 3457    Accepted Submission(s): 1020 Problem Description Starvae very like play a number game in the n*n Matrix. A positive intege

POJ 3020 Antenna Placement(二分图建图训练 + 最小路径覆盖)

题目链接:http://poj.org/problem?id=3020 Antenna Placement Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 6692   Accepted: 3325 Description The Global Aerial Research Centre has been allotted the task of building the fifth generation of mobi

poj3281-Dining ,最大流,建图

点击打开链接 分析: 求最大流 建图: 拆点 牛拆成左边与食物相连的左牛 和 右边与饮料相连的右牛 1.s->食物 连边 2.食物->左牛 3.左牛->右牛 4.右牛->饮料 5.饮料->t 边的方向为 s->食物->左牛->右牛->饮料->t #include <cstdio> #include <cstring> #include <algorithm> #include <vector> #i

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

题目大意: 在一个农场里面,有k个挤奶机,编号分别是 1..k,有c头奶牛,编号分别是k+1 .. k+c,每个挤奶机一天最让可以挤m头奶牛的奶,奶牛和挤奶机之间用邻接矩阵给出距离.求让所有奶牛都挤到 奶的情况下,走的最远的那头奶牛走的距离最小是多少. 数据保证有解. 算法讨论: 首先可以想到是二分,然后在选择流网络的时候,一开始选择的最小费用最大流,让二分的边权充当最小费用,但是这样跑发现每次二分的是我们要跑的答案,不可行.所以就改用最大流. 最大流肯定是在二分的情况下判定最大流是否等于c,即

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

<题目链接> 题目大意: 有K台挤奶机和C头奶牛,都被视为物体,这K+C个物体之间存在路径.给出一个 (K+C)x(K+C) 的矩阵A,A[i][j]表示物体i和物体j之间的距离,有些物体之间可能没有直接通路. 每台挤奶机可以容纳m头奶牛去挤奶,且每个奶牛仅可以去往一台挤奶机.现在安排这C头奶牛去挤奶,每头奶牛会去往某个挤奶机,求出这C头奶牛去其挤奶的最长路径的最小值. 解题分析: 因为要求最长路径的最小值,所以我们很容易想到二分答案.由于数据量较小,所以我们先用floyed求出所有点之间的最

POJ 2112 /// 最大流+floyd+二分

题目大意: 有 k台挤奶机 和 c头奶牛 每台挤奶机最多为m头奶牛服务 给定所有挤奶机和奶牛两两之间的距离 求一种分配 使得 奶牛与挤奶机之间的最远距离 最小化 floyd求得所有挤奶机与奶牛两两之间的最短距离 二分一个最远距离M 建图 超级源点s与所有奶牛连容量为1的边 所有挤奶机与超级汇点t连容量为m的边 奶牛与挤奶机之间距离<=M的连容量为1的边 跑s到t的最大流 若最大流为c 说明这个最远距离M是符合要求的 #include<iostream> #include<cstdi

【BZOJ-2879】美食节 最小费用最大流 + 动态建图

2879: [Noi2012]美食节 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 1366  Solved: 737[Submit][Status][Discuss] Description CZ市为了欢迎全国各地的同学,特地举办了一场盛大的美食节.作为一个喜欢尝鲜的美食客,小M自然不愿意错过这场盛宴.他很快就尝遍了美食节所有的美食.然而,尝鲜的欲望是难以满足的.尽管所有的菜品都很可口,厨师做菜的速度也很快,小M仍然觉得自己桌上没有已经摆在别人