POJ - 3268 Silver Cow Party (最短路)

                                       Silver Cow Party

Description

One cow from each of N farms (1 ≤ N ≤ 1000) conveniently numbered 1..N is going to attend the big cow party to be held at farm #X (1 ≤ XN). A total of M (1 ≤ M ≤ 100,000) unidirectional (one-way roads connects pairs of farms; road i requires Ti (1 ≤ Ti ≤ 100) units of time to traverse.

Each cow must walk to the party and, when the party is over, return to her farm. Each cow is lazy and thus picks an optimal route with the shortest time. A cow's return route might be different from her original route to the party since roads are one-way.

Of all the cows, what is the longest amount of time a cow must spend walking to the party and back?

Input

Line 1: Three space-separated integers, respectively: N, M, and X
Lines 2..M+1: Line i+1 describes road i with three space-separated integers: Ai, Bi, and Ti. The described road runs from farm Ai to farm Bi, requiring Ti time units to traverse.

Output

Line 1: One integer: the maximum of time any one cow must walk.

Sample Input

4 8 2
1 2 4
1 3 2
1 4 7
2 1 1
2 3 5
3 1 2
3 4 4
4 2 3

Sample Output

10

Hint

Cow 4 proceeds directly to the party (3 units) and returns via farms 1 and 3 (7 units), for a total of 10 time units.

题意描述:

n个农场m条路x号农场为聚集点,求出从各个农场到达聚集点,再返回各个农场,最短路径中的最大值。m条路为单向,起点、终点距离。

解题思路:

由题意可知求出各个点到x的最小距离,x到各个点的最小距离,对应相加找出最大的数,弗洛伊德会时间超限,可以进行两遍迪杰斯特拉:将路径正着存储,运用一遍迪杰斯特拉求出x点到各点的最短距离,路径倒着存储,运用迪杰斯特拉求出各点到x的最短路径,加在一起找出最大值;也可以用Bellman-Ford优先队列,直接求出各个点之间的最短距离,将各点到x,x到个点距离进行对应相加,找最大,也不会时间超限。

迪杰斯特拉:

#include<stdio.h>
#include<string.h>
# define inf 99999999
int map1[1010][1010],map2[1010][1010],dis1[1010],dis2[1010],book[1010];
int main()
{
	int n,m,x,i,j,k,u,v,a,b,c,min,max;
	while(scanf("%d%d%d",&n,&m,&x)!=EOF)
	{
		for(i=1;i<=n;i++)
			for(j=1;j<=n;j++)
			{
				if(i==j)
				{
					map1[i][j]=0;
					map2[i][j]=0;
				}
				else
				{
					map1[i][j]=inf;
					map2[i][j]=inf;
				}
			}
		for(i=1;i<=m;i++)
		{
			scanf("%d%d%d",&a,&b,&c);
			if(c<map1[a][b])
			{
				map1[a][b]=c;
			}
			if(c<map2[b][a])
			{
				map2[b][a]=c;
			}
		}
		for(i=1;i<=n;i++)
		{
			dis1[i]=map1[x][i];
			dis2[i]=map2[x][i];
		}
		memset(book,0,sizeof(book));
		book[x]=1;
		for(i=1;i<n;i++)
		{
			min=inf;
			for(j=1;j<=n;j++)
			{
				if(book[j]==0&&dis1[j]<min)
				{
					min=dis1[j];
					u=j;
				}
			}
			book[u]=1;
			for(v=1;v<=n;v++)
			{
				if(dis1[v]>dis1[u]+map1[u][v])
					dis1[v]=dis1[u]+map1[u][v];
			}
		}
		memset(book,0,sizeof(book));
		book[x]=1;
		for(i=1;i<n;i++)
		{
			min=inf;
			for(j=1;j<=n;j++)
			{
				if(book[j]==0&&dis2[j]<min)
				{
					min=dis2[j];
					u=j;
				}
			}
			book[u]=1;
			for(v=1;v<=n;v++)
			{
				if(dis2[v]>dis2[u]+map2[u][v])
					dis2[v]=dis2[u]+map2[u][v];
			}
		}
		max=-1;
		for(i=1;i<=n;i++)
		{
			if(max<dis1[i]+dis2[i])
				max=dis1[i]+dis2[i];
		}
		printf("%d\n",max);
	}
	return 0;
}

Bellman-Ford优先队列:

#include<stdio.h>
#include<string.h>
# define inf 99999999
int n,m,i,j,k,x,h;
int u[100010],v[100010],w[100010];
int first[10010],next[100010];
int dis[10010][10010],book[10010];
int q[1000010];
int main()
{
	int head,tail,max;
	while(scanf("%d%d%d",&n,&m,&x)!=EOF)
	{
		for(i=1;i<=n;i++)
				first[i]=-1;
		for(i=1;i<=m;i++)
		{
			scanf("%d%d%d",&u[i],&v[i],&w[i]);
			next[i]=first[u[i]];
			first[u[i]]=i;
		}
		for(h=1;h<=n;h++)
		{
			
			for(i=1;i<=n;i++)
				dis[h][i]=inf;
			dis[h][h]=0;
			for(i=1;i<=n;i++)
				book[i]=0;
			
			head=1;
			tail=1;
			q[tail]=h;
			tail++;
			book[h]=1;
			while(head<tail)
			{
				k=first[q[head]];
				while(k!=-1)
				{
					if(dis[h][v[k]]>dis[h][u[k]]+w[k])
					{
						dis[h][v[k]]=dis[h][u[k]]+w[k];
						if(book[v[k]]==0)
						{
							q[tail]=v[k];
							tail++;
							book[v[k]]=1;
						}
					}
					k=next[k];
				}
				book[q[head]]=0;
				head++;
			}
		}
		max=-1;
		for(i=1;i<=n;i++)
		{
			if(max<dis[x][i]+dis[i][x])
				max=dis[x][i]+dis[i][x];
		}
		printf("%d\n",max);
	}
	return 0;
}
扫描二维码关注公众号,回复: 2615816 查看本文章

猜你喜欢

转载自blog.csdn.net/kongsanjin/article/details/81432450