poj 2112 Optimal Milking 网络流 最大流

题目大意:农场有k个挤奶器,每个挤奶器最多容纳m头奶牛,所有奶牛和挤奶器之间的距离已知,安排奶牛挤奶方案使得所有奶牛中走的最大距离最小化。

利用最大流来做,奶牛和挤奶器看做图中节点,先用floyd算出每个节点之间的最小距离,二分最大距离d,然后建图,边长大于d的都去掉,然后建立网络,引入源点和汇点,源点到每个奶牛节点连接一条容量为一的边,挤奶器节点与汇点连接一条容量为m的边,奶牛节点与挤奶器节点间连接容量为一的边(如果之间有边的话),然后求最大流,不断二分。

代码为dinic算法

#include <stdio.h>
#include <string.h>
#define MAX 300
#define INF 10000000
int dis[MAX][MAX],map[MAX][MAX];
bool sign[MAX][MAX],used[MAX];
int K,C,n,M;
int min(int a,int b)
{
	if(a>b)
		return b;
	else return a;
}
void build(int mid)
{
	int i,j;
	memset(map,0,sizeof(map));
	for(i=K+1;i<=n;i++) map[0][i]=1;
	for(i=1;i<=K;i++) map[i][n+1]=M;
	for(i=K+1;i<=n;i++)
	{
		for(j=1;j<=K;j++)
			if(dis[i][j]<=mid)
				map[i][j]=1;
	}
}

bool bfs()
{
	memset(used,0,sizeof(used));
	memset(sign,0,sizeof(sign));
	int queue[100*MAX]={0};
	queue[0]=0;
	used[0]=1;
	int t=1,f=0;
	while(f<t)
	{
		for(int i=0;i<=n+1;i++)
		{
			if(!used[i]&&map[queue[f]][i])
			{
				queue[t++]=i;
				used[i]=1;
				sign[queue[f]][i]=1;
			}
		}
		f++;
	}
	if(used[n+1]) return true;
	else return false;
}

int dfs(int v,int sum)
{
	int i,s,t;
	if(v==n+1) return sum;
	s=sum;
	for(i=0;i<=n+1;i++)
	{
		if(sign[v][i])
		{
			t=dfs(i,min(map[v][i],sum));
			map[v][i]-=t;
			map[i][v]+=t;
			sum-=t;
		}
	}
	return s-sum;
}

int main()
{
	int i,j,k,l,r,mid,ans;
	scanf("%d%d%d",&K,&C,&M);
	n=K+C;
	for(i=1;i<=n;i++)
	{
		for(j=1;j<=n;j++)
		{
			scanf("%d",&dis[i][j]);
			if(dis[i][j]==0) dis[i][j]=INF;
		}
	}
	for(k=1;k<=n;k++)
		for(i=1;i<=n;i++)
			for(j=1;j<=n;j++)
				if(dis[i][j]>dis[i][k]+dis[k][j])
					dis[i][j]=dis[i][k]+dis[k][j];
	l=0;r=10000;
	while(l<r)
	{
		mid=(l+r)/2;
		ans=0;
		build(mid);
		while(bfs()) ans+=dfs(0,INF);
		if(ans>=C) r=mid;
		else l=mid+1;
	}
	printf("%d
",r);
	return 0;
}


 

 

原文地址:https://www.cnblogs.com/vermouth/p/3710209.html