●POJ poj 2112 Optimal Milking

●题目大意:

给出K个挤奶机器(编号1~K),C头牛(编号K+1~K+C)(机器和牛各在不同的地方)和每台机器最多可M头牛挤奶;

然后以邻接矩阵告诉各点间的直接距离(不同的地方间若直接距离等于0,则表明没有直接连路)。

目的是要让每一头牛都要去一台机器处被挤奶,要使行走路程最大的牛的路程最小。goto

●题解:

刚拿到题时很Mengbi,搞了一段时间后才发现每个点可以去多次……

因为点数只有不超过230个,那么我们可以求出每个牛到每个机器的最短距离(自然是floyd嘛),那么问题变成了将牛分配至机器,不同的牛分配到不同的机器有不同的代价(即计算出的最短距离),且每个机器的能接受的牛的数量有限,要求出最大代价的最小值(明摆着套路二分答案嘛)。

至此,思路渐渐清晰,先floyd求每个牛到每个机器的最短距离,然后二分答案(lim 表示),开始建图,跑网络流;

建图&网络流(对于每一个二分出来的lim):

1、源点 s 向各头牛连一条容量为1的有向边;

2、枚举牛和机器的”组合“,若 A 牛到 B 机器的(最短)距离小于 lim ,则从 A 向 B 连一条容量为 inf(只要容量大于0即可) 的有向边;

3、从各机器向源点 E 连一条容量为1的有边;

4、用最大流求图中的流量,若流量等于牛的数量,就,咳咳.…..

总:floyd+二分+最大流

#include<cstdio>
#include<cstring>
#include<iostream>
#define oo (0x3f3f3f3f)
using namespace std;
struct edge{
	int to,next,cap;
}e[250*250*2];
int mp[250][250],head[250],q[250],d[250];
int k,c,m,l=+oo,r=-1,mid,ent;
void add(int u,int v,int cap){
	e[ent]=(edge){v,head[u],cap};head[u]=ent++;
	e[ent]=(edge){u,head[v],0};head[v]=ent++;
}
bool bfs(int s,int t)
{
	int ll=0,rr=1; q[rr]=s;
	memset(d,0,sizeof(d)); d[s]=1;
	while(ll<rr)
	{
		ll++; int u=q[ll];
		for(int i=head[u];~i;i=e[i].next) if(e[i].cap>0)
		{
			int v=e[i].to; if(d[v]) continue;
			d[v]=d[u]+1; q[++rr]=v;
		}
	}
	return d[t];
}
int dfs(int u,int t,int flow)
{
	if(u==t) return flow; int flowout=0,f;
	for(int i=head[u];i!=-1;i=e[i].next)
	{
		int v=e[i].to;
		if(d[v]!=d[u]+1) continue;
		f=dfs(v,t,min(flow,e[i].cap));
		flowout+=f; flow-=f;
		e[i].cap-=f; e[i^1].cap+=f;
		if(flow==0) break;
	}
	return flowout;
}
bool check(int s,int t)
{
	memset(head,-1,sizeof(head));ent=0;
	for(int i=k+1;i<=k+c;i++)
	  for(int j=1;j<=k;j++)
	  	if(mp[i][j]>-1&&mp[i][j]<=mid) add(i,j,1);
	for(int i=k+1;i<=k+c;i++) add(s,i,1);
	for(int i=1;i<=k;i++) add(i,t,m);
	int flow=0;
	while(bfs(s,t)) flow+=dfs(s,t,+oo);
	return flow==c;
}
void solve(int s,int t)
{
	int ans=0;
	while(l<=r)
	{
		mid=(l+r)/2;
		if(check(s,t)) ans=mid,r=mid-1;	else l=mid+1;
	}
	printf("%d",ans);
}
void floyd()
{
	for(int o=1;o<=k+c;o++)
	  for(int i=1;i<=k+c;i++)
		for(int j=1;j<=k+c;j++)
			if(mp[i][o]>-1&&mp[o][j]>-1&&(mp[i][j]==-1||mp[i][o]+mp[o][j]<mp[i][j]))
				mp[i][j]=mp[i][o]+mp[o][j];
	for(int i=k+1;i<=k+c;i++)
	  for(int j=1;j<=k;j++)
	   	l=0,r=max(r,mp[i][j]);
}
int main()
{
	scanf("%d%d%d",&k,&c,&m);
	memset(mp,-1,sizeof(mp));
	for(int i=1;i<=k+c;i++) for(int j=1;j<=k+c;j++)
	{
		scanf("%d",&mp[i][j]);
		if(mp[i][j]==0&&i!=j) mp[i][j]=-1;
	}
	floyd(); solve(0,k+c+1);
	return 0;
}
时间: 2024-08-24 14:47:44

●POJ poj 2112 Optimal Milking的相关文章

POJ 2112 Optimal Milking (二分 + floyd + 网络流)

POJ 2112 Optimal Milking 链接:http://poj.org/problem?id=2112 题意:农场主John 将他的K(1≤K≤30)个挤奶器运到牧场,在那里有C(1≤C≤200)头奶牛,在奶牛和挤奶器之间有一组不同长度的路.K个挤奶器的位置用1-K的编号标明,奶牛的位置用K+1-K+C 的编号标明.每台挤奶器每天最多能为M(1≤M≤15)头奶牛挤奶.寻找一个方案,安排每头奶牛到某个挤奶器挤奶,并使得C 头奶牛需要走的所有路程中的最大路程最小.每个测试数据中至少有一

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

POJ 2112—— Optimal Milking——————【多重匹配、二分枚举答案、floyd预处理】

Optimal Milking Time Limit:2000MS     Memory Limit:30000KB     64bit IO Format:%I64d & %I64u Submit Status Practice POJ 2112 Description FJ has moved his K (1 <= K <= 30) milking machines out into the cow pastures among the C (1 <= C <= 20

POJ 2112 Optimal Milking

Optimal Milking Time Limit: 2000ms Memory Limit: 30000KB This problem will be judged on PKU. Original ID: 211264-bit integer IO format: %lld      Java class name: Main FJ has moved his K (1 <= K <= 30) milking machines out into the cow pastures amon

POJ 2112 Optimal Milking(最大流)

题目链接:http://poj.org/problem?id=2112 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

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

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

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 二分+Floyd+最大流

原题:http://poj.org/problem?id=2112 #include<cstdio> #include<cstring> #include<string> #include<queue> #include<vector> #include<algorithm> #define inf 0x3f3f3f3f using namespace std; const int maxn = 250; int dis[maxn][