poj 2112 (最大流+二分)

题意:有k台挤奶机,c头奶牛,给出这k+c个实体间的距离,求出每头奶牛都到一台挤奶机去,怎么分配使奶牛走的最大距离最小。

用二分枚举最大距离,,,,





 

#include<stdio.h>

#include<string.h>

#define N 500

#define inf 0x3fffffff

int map[N][N],dis[N],gap[N],head[N],num,n,m,D,start,end,ans;

struct edge

{

	int st,ed,flow,next;

}E[N*40];

void addedge(int x,int y,int w)

{

	E[num].st=x;E[num].ed=y;E[num].flow=w;E[num].next=head[x];head[x]=num++;

	E[num].st=y;E[num].ed=x;E[num].flow=0;E[num].next=head[y];head[y]=num++;

}

int dfs(int u,int minflow)

{

	if(u==end)return minflow;

	int i,v,f,min_dis=ans-1,flow=0;

	for(i=head[u];i!=-1;i=E[i].next)

	{

		if(E[i].flow>0)

		{

			v=E[i].ed;

			if(dis[v]+1==dis[u])

			{

				f=dfs(v,E[i].flow>minflow-flow?minflow-flow:E[i].flow);

				E[i].flow-=f;

				E[i^1].flow+=f;

				flow+=f;

				if(flow==minflow)break;

				if(dis[start]>=ans)return flow;

			}

			min_dis=min_dis>dis[v]?dis[v]:min_dis;

		}

	}

	if(flow==0)

	{

		if(--gap[dis[u]]==0)

			dis[start]=ans;

		dis[u]=min_dis+1;

		gap[dis[u]]++;

	}

	return flow;

}

int isap()

{

	int maxflow=0;

	memset(dis,0,sizeof(dis));

	memset(gap,0,sizeof(gap));

	gap[0]=ans;

	while(dis[start]<ans)

		maxflow+=dfs(start,inf);

	return maxflow;

}

void makemap(int DD)

{

	int i,j;

	memset(head,-1,sizeof(head));

	num=0;

	for(i=1;i<=m;i++)

		addedge(start,i+n,1);

	for(i=1;i<=n;i++)

		addedge(i,end,D);

	for(i=n+1;i<=n+m;i++)

		for(j=1;j<=n;j++)

		{

			if(map[i][j]<=DD&&map[i][j]!=0)

				addedge(i,j,1);

		}

}

int main()

{

	int i,j,k,left,right,mid;

	while(scanf("%d%d%d",&n,&m,&D)!=-1)

	{

		left=0;right=0;start=0;end=n+m+1;ans=end+1;

		memset(map,0,sizeof(map));

		for(i=1;i<=n+m;i++)

			for(j=1;j<=n+m;j++)

				scanf("%d",&map[i][j]);

			for(k=1;k<=n+m;k++)

			{

				for(i=1;i<=n+m;i++)

				{

					if(map[i][k]==0)continue;//0表示不连通

					for(j=1;j<=n+m;j++)

					{

						if(map[k][j]==0||i==j)continue;

						if(map[i][j]==0||map[i][j]>map[i][k]+map[k][j])

							map[i][j]=map[i][k]+map[k][j];

						if(right<map[i][j])

							right=map[i][j];

					}

				}

			}

			while(left<right)

			{

				mid=(left+right)/2;

				makemap(mid);

				int sum=isap();

				if(sum==m)

					right=mid;

				else left=mid+1;

			}

			printf("%d\n",right);

	}

	return 0;

}


 

 

你可能感兴趣的:(poj)