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,cap,flow,next;
 12 }edge[MAXM];
 13 int vs,vt,NE,NV;
 14 int head[MAXN];
 15
 16 void addEdge(int u,int v,int cap){
 17     edge[NE].v=v; edge[NE].cap=cap; edge[NE].flow=0;
 18     edge[NE].next=head[u]; head[u]=NE++;
 19     edge[NE].v=u; edge[NE].cap=0; edge[NE].flow=0;
 20     edge[NE].next=head[v]; head[v]=NE++;
 21 }
 22
 23 int level[MAXN];
 24 int gap[MAXN];
 25 void bfs(){
 26     memset(level,-1,sizeof(level));
 27     memset(gap,0,sizeof(gap));
 28     level[vt]=0;
 29     gap[level[vt]]++;
 30     queue<int> que;
 31     que.push(vt);
 32     while(!que.empty()){
 33         int u=que.front(); que.pop();
 34         for(int i=head[u]; i!=-1; i=edge[i].next){
 35             int v=edge[i].v;
 36             if(level[v]!=-1) continue;
 37             level[v]=level[u]+1;
 38             gap[level[v]]++;
 39             que.push(v);
 40         }
 41     }
 42 }
 43
 44 int pre[MAXN];
 45 int cur[MAXN];
 46 int ISAP(){
 47     bfs();
 48     memset(pre,-1,sizeof(pre));
 49     memcpy(cur,head,sizeof(head));
 50     int u=pre[vs]=vs,flow=0,aug=INF;
 51     gap[0]=NV;
 52     while(level[vs]<NV){
 53         bool flag=false;
 54         for(int &i=cur[u]; i!=-1; i=edge[i].next){
 55             int v=edge[i].v;
 56             if(edge[i].cap!=edge[i].flow && level[u]==level[v]+1){
 57                 flag=true;
 58                 pre[v]=u;
 59                 u=v;
 60                 //aug=(aug==-1?edge[i].cap:min(aug,edge[i].cap));
 61                 aug=min(aug,edge[i].cap-edge[i].flow);
 62                 if(v==vt){
 63                     flow+=aug;
 64                     for(u=pre[v]; v!=vs; v=u,u=pre[u]){
 65                         edge[cur[u]].flow+=aug;
 66                         edge[cur[u]^1].flow-=aug;
 67                     }
 68                     //aug=-1;
 69                     aug=INF;
 70                 }
 71                 break;
 72             }
 73         }
 74         if(flag) continue;
 75         int minlevel=NV;
 76         for(int i=head[u]; i!=-1; i=edge[i].next){
 77             int v=edge[i].v;
 78             if(edge[i].cap!=edge[i].flow && level[v]<minlevel){
 79                 minlevel=level[v];
 80                 cur[u]=i;
 81             }
 82         }
 83         if(--gap[level[u]]==0) break;
 84         level[u]=minlevel+1;
 85         gap[level[u]]++;
 86         u=pre[u];
 87     }
 88     return flow;
 89 }
 90
 91 int d[MAXN][MAXN],k,c,m,N;
 92 bool available(int mx){
 93     memset(head,-1,sizeof(head));
 94     for(int i=1; i<=k; ++i) addEdge(i,vt,m);
 95     for(int i=1; i<=c; ++i) addEdge(vs,i+k,1);
 96     for(int i=1; i<=c; ++i){
 97         for(int j=1; j<=k; ++j){
 98             if(d[i+k][j]==0 || d[i+k][j]>mx) continue;
 99             addEdge(i+k,j,1);
100         }
101     }
102     return ISAP()==c;
103 }
104 inline void floyd(){
105     for(int k=1; k<=N; ++k){
106         for(int i=1; i<=N; ++i){
107             if(!d[i][k]) continue;
108             for(int j=1; j<=N; ++j){
109                     if(d[k][j] && (d[i][j]==0 || d[i][j]>d[i][k]+d[k][j])) d[i][j]=d[i][k]+d[k][j];
110             }
111         }
112     }
113 }
114 int main(){
115     scanf("%d%d%d",&k,&c,&m);
116     N=k+c;
117
118     vs=0; vt=N+1; NV=vt+1;
119
120     for(int i=1; i<=N; ++i){
121         for(int j=1; j<=N; ++j) scanf("%d",&d[i][j]);
122     }
123     floyd();
124
125     int l=0,r=INF;
126     while(l<r){
127         int mid=l+r>>1;
128         if(available(mid)) r=mid;
129         else l=mid+1;
130     }
131     printf("%d",l);
132     return 0;
133 }
时间: 2024-08-06 07:08:57

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

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) co

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

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

poj 2112 Optimal Milking 最大流

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

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

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

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