首页 > 代码库 > POJ 2112 最大流+二分+(建图:最重要的)
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.
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.
* 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 20 3 2 1 13 0 3 2 02 3 0 1 01 2 1 0 21 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 }
POJ 2112 最大流+二分+(建图:最重要的)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。