您的位置:首页 > 其它

最短路径 【Dijkstra】

2015-01-25 13:16 239 查看
/*最短路径问题 
Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 32768/32768K (Java/Other)
Total Submission(s) : 0   Accepted Submission(s) : 0
Font: Times New Roman | Verdana | Georgia 
Font Size: ← →
Problem Description
给你n个点,m条无向边,每条边都有长度d和花费p,给你起点s终点t,要求输出起点到终点的最短距离及其花费,如果最短距离有多条路线,则输出花费最少的。 
Input
输入n,m,点的编号是1~n,然后是m行,每行4个数 a,b,d,p,表示a和b之间有一条边,且其长度为d,花费为p。最后一行是两个数 s,t;起点s,终点。
n和m为0时输入结束。
(1<n<=1000, 0<m<100000, s != t) 
Output
输出 一行有两个数, 最短距离及其花费。 
Sample Input
3 2
1 2 5 6
2 3 4 5
1 3
0 0
Sample Output
9 11
Source
浙大计算机研究生复试上机考试-2010年 
*/
#include<stdio.h>
#include<string.h>
#define MAX 1000000000//this can't be 0x7FFFFFFF
int map1[1010][1010], map2[1010][1010], start, end, dij1[1010], dij2[1010], n, vis[1010];
void dij(int x, int y)//every time get one min point until the "end" .
{
	int i, j, min1 = MAX, min2 = MAX;
	for(i = 1; i < n+1; ++i)//get the min point
	{
		if(!vis[i] && min1 >= dij1[i])//if the point didn't visit
		{
			if(min1 == dij1[i])//when the distance is same
			{
				if(min2 > dij2[i])//get the min money
				{
					min2 = dij2[i];
					j = i;//record the point
				}
			}
			else
			{
				min1 = dij1[i];
				min2 = dij2[i];
				j =  i;
			}
		}
	}
	vis[j] = 1;// the point has been visited
	if(j == y)//if get the end
	return ;
	for(i = 1; i < n+1; ++i)//update
	{
		if(!vis[i])
		{
			if(dij1[i] >= dij1[j] + map1[i][j])
			{
				if(dij1[i] == dij1[j] + map1[i][j])//if the distance is same
				{
					if(dij2[i] > dij2[j] + map2[i][j])//judge the money
					{
						dij2[i] = dij2[j] + map2[i][j];
					}
				}
				else
				{
					dij1[i] = dij1[j] + map1[i][j];
					dij2[i] = dij2[j] + map2[i][j];
				} 
			}
		}
	}
	dij(x, y);
}
int main()
{
	int  m, i, j;
	while(scanf("%d%d", &n, &m) != EOF && (n || m))
	{
		int a, b, c, d;
		for(i = 1; i < n+1; ++i)//initial
		{
			for( j = 1; j < n+1; ++j)
			{
					map1[i][j] = map1[j][i] = MAX;
					map2[i][j] = map2[j][i] = MAX;
			}
		}
		for(i = 0; i < m; ++i)
		{
			scanf("%d%d%d%d", &a, &b, &c, &d);
			if(map1[a][b] > c)
			{
				map1[a][b] = map1[b][a] = c;
				map2[a][b] = map2[b][a] = d;
			}
			else if(map1[a][b] == c)
			{
				if(map2[a][b] > d)
				map2[a][b] = map2[b][a] = d;
			}
		}
		scanf("%d%d", &start, &end);
		memset(vis, 0, sizeof(vis));
		dij1[start] = 0;//start
		dij2[start] = 0;
		vis[start] = 1;
		for(i = 1; i < n+1; ++i)
		{
			if(i != start)
			{
				dij1[i] = map1[start][i];
				dij2[i] = map2[start][i];
			}
		}
		dij(start, end);
		printf("%d %d\n", dij1[end], dij2[end]);
	}
	return 0;
}

题意:给定n个点,m条无向边,并给出起点和终点,每条边都有个长度和花费值,求起点到终点的最短距离,如果最短距离有重复的,则选择花费最小的那组数据。

思路:由Dij算法给出思路,即以起点为原点,求出每一个点到起点的最短距离以及花费 ,每求出一个点则将这个点标记,并且更新未标记的点到起点的距离,更新方法即判断该点原本的距离和(起点到被标记的点加上被标记的点到该点的距离)谁小,如果遇到更新前后距离相等的,则以花费为标准进行判断,选择最小的作为新的数据,直至遇到终点,则起点到终点的最小距离就出来了。

注意:初始化时,对于输入中未给出的边都默认为无穷大,这里无穷大定义应适当注意范围,在判断时会遇到相加的操作(避免超出int范围)。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: