hdu 2485

//拆点建边,组成一个图,求最大流,先两次bfs,搜出各点到1点和n点的最短路,然后拆点时,如果这个点到1点和n点的最短路之和小于等于k,就把i到i+n的流量设为1,否则为0,图中原来的边的流量为inf,最后就是一个最大流的问题了;

//这题用最小费用流也可解,稍后补上代码

//最大流的代码:

#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
#define inf 1000000
int bdis[55],hdis[55],vis[110];
int map[55][55],dis[55],n,cap[110][110];
void bfs(int start)
{
	int i;
	queue <int> que;
	for(i=1;i<=n;i++)
		dis[i]=inf;
	que.push(start);
	dis[start]=0;
	while(!que.empty())
	{
		int u=que.front();
		que.pop();
		for(i=1;i<=n;i++)
		{
			if(map[u][i]&&dis[u]+1<dis[i])
			{
				dis[i]=dis[u]+1;
				que.push(i);
			}
		}
	}
}

int pre[110];
int maxflow(int start,int end)
{
	int i,res=0,Min;
	while(1)
	{
		queue <int> que;
		memset(vis,0,sizeof(vis));
		que.push(start);
		vis[start]=1;
		while(!que.empty())
		{
			int u=que.front();
			que.pop();
			if(vis[end])break;
			for(i=start;i<=end;i++)
			{
				if(!vis[i]&&cap[u][i]>0)
				{
					vis[i]=1;
					pre[i]=u;
					que.push(i);
				}
			}
		}
		if(!vis[end])break;
		Min=inf;
		for(i=end;i!=start;i=pre[i])
		{
			if(cap[pre[i]][i]<Min)Min=cap[pre[i]][i];
		}
		res+=Min;
		for(i=end;i!=start;i=pre[i])
		{
			cap[pre[i]][i]-=Min;
			cap[i][pre[i]]+=Min;
		}
	}
	return res;
}
int mp[55][55];
int main()
{
	int m,k,i,j,a,b;
	while(scanf("%d%d%d",&n,&m,&k),n+m+k)
	{
		for(i=1;i<=n;i++)
			for(j=1;j<=n;j++)
				map[i][j]=mp[i][j]=0;
		for(i=1;i<=m;i++)
		{
			scanf("%d%d",&a,&b);
			mp[a][b]=1;
			map[b][a]=1;
			map[a][b]=1;
		}
		bfs(1);
		for(i=1;i<=n;i++)bdis[i]=dis[i];
		bfs(n);
		for(i=1;i<=n;i++)hdis[i]=dis[i];

		for(i=1;i<=2*n;i++)
			for(j=1;j<=2*n;j++)
				cap[i][j]=0;
		for(i=1;i<=n;i++)
		{
			for(j=1;j<=n;j++)
				if(mp[i][j])
					cap[i+n][j]=inf;
			if(bdis[i]+hdis[i]<=k)
				cap[i][i+n]=1;
		}
		cap[1][1+n]=inf;
		cap[n][n+n]=inf;
		printf("%d\n",maxflow(1,n+n));
	}
	return 0;
}


你可能感兴趣的:(hdu 2485)