Dijkstra算法实现==2014hiho第23周最短路问题


题目:最短路径

时间限制: 10000ms
单点时限: 1000ms
内存限制: 256MB
描述

万圣节的早上,小Hi和小Ho在经历了一个小时的争论后,终于决定了如何度过这样有意义的一天——他们决定去闯鬼屋!

在鬼屋门口排上了若干小时的队伍之后,刚刚进入鬼屋的小Hi和小Ho都颇饥饿,于是他们决定利用进门前领到的地图,找到一条通往终点的最短路径。

鬼屋中一共有N个地点,分别编号为1..N,这N个地点之间互相有一些道路连通,两个地点之间可能有多条道路连通,但是并不存在一条两端都是同一个地点的道路。那么小Hi和小Ho至少要走多少路程才能够走出鬼屋去吃东西呢?

       
输入

每个测试点(输入文件)有且仅有一组测试数据。

在一组测试数据中:

第1行为4个整数N、M、S、T,分别表示鬼屋中地点的个数和道路的条数,入口(也是一个地点)的编号,出口(同样也是一个地点)的编号。

接下来的M行,每行描述一条道路:其中的第i行为三个整数u_i, v_i, length_i,表明在编号为u_i的地点和编号为v_i的地点之间有一条长度为length_i的道路。

对于100%的数据,满足N<=10^3,M<=10^4, 1 <= length_i <= 10^3, 1 <= S, T <= N, 且S不等于T。

对于100%的数据,满足小Hi和小Ho总是有办法从入口通过地图上标注出来的道路到达出口。

输出

对于每组测试数据,输出一个整数Ans,表示那么小Hi和小Ho为了走出鬼屋至少要走的路程。

样例输入
5 23 5 4
1 2 708
2 3 112
3 4 721
4 5 339
5 4 960
1 5 849
2 5 98
1 4 99
2 4 25
2 1 200
3 1 146
3 2 106
1 4 860
4 1 795
5 4 479
5 4 280
3 4 341
1 4 622
4 2 362
2 3 415
4 1 904
2 1 716
2 5 575
样例输出
123


在hiho上看到这道题,大学期间也学到过Dijkstra最短路径算法,但当时没学好,今天花了1个多小时重新看了一下,总算看明白,开心。

另外Dijkstra老爷子还是很不错的,前几天去笔试让写知道的计算机界有贡献的人,想了半天只写出图灵诺依曼,惭愧。

这里有一篇关于Dijkstra算法的文章,还有动图,推荐一下:

http://www.cnblogs.com/biyeymyhjob/archive/2012/07/31/2615833.html


下面是我给出的算法的描述(感觉虽然没将算法原理讲清,但是便于实现):

1.初始化将起始点加入到S集合(默认其余的元素在U集合),选择起始点并设置dist[i],dist[i]表示i点到起始点的距离。

2.将U集合中点逐“1”加入到S集合中,加入规则:谁距离起始点最近谁加入S集合(mindist)。加入后更新dist数组重新设置各点到起始点距离。(eg:A为起始点且在S集合,B,C...在U集合,若AB=2(minA*),AC=无穷...BC=3,将B加入到S集合中后,由于AC>AB+BC,所以update dist[iC] = 5,对于U中其它元素同理)

3.重复步骤2直到S集合满。dist即最终结果集。


代码实现:

//dijkstra Ëã·¨Çó×î¶Ì·ÎÊÌâ 
//Ë㷨˵Ã÷£º
/*
   1.³õʼ»¯£¬Ñ¡¶¨³õʼµã²¢½«³õʼµã´æÈëS¼¯ºÏÖУ» 
   2.½«U¼¯ºÏÖеĵãÖð 1 ¼ÓÈëÖÁS¼¯ºÏÖУ¬¼ÓÈë¹æÔò£ºË­µ½Æðʼµã¾àÀë×î½ü¾Í½«Ë­¼ÓÈ룬¼ÓÈëºóÖØмÆÁ¿U¼¯ºÏÖеĵ㵽ÆðʼµãµÄ¾àÀ룻  
     (È磺³õʼµãΪA£¬¼¯ºÏSÖе±Ç°Ö»´æÔÚA£¬¼¯ºÏUÖÐÓÐB,CÈô¸É¸öµã£¬AB£¨A*ÖÐ×îСµÄ£©=2£¬AC=ÎÞÇBC=3£¬¸ù¾Ý¹æÔòBµã¼ÓÈ뼯ºÏSºó£¬ÓÉÓÚAC>AB+BC,
	 ËùÒÔAC±»ÖØÖÃΪ5) 
   3.Öظ´¶þ£¬Ö±µ½È«²¿µã±»¼ÓÈëµ½S¼¯ºÏΪֹ£» 
   add:¹Ø¼üÊý¾Ý½á¹¹£¬Í¼µÄ¼Ç¼¶þάÊý×émap
                     Ç°Çý¼Ç¼һλÊý×éprev
					 ¾àÀë¼Ç¼һάÊý×édist
					 s¼¯ºÏ±êʶÊý×ésMem
					 s¼¯ºÏÊý¾ÝÊýÁ¿ 
*/ 
#include<stdio.h>

long map[1002][1002] ; //map[i][j]¼Ç¼iµ½jµãµÄ¾àÀë 
long dist[1002] ; //dist[i]¼Ç¼iµ½Ô­µãµÄ×î¶Ì¾àÀë 
int sMem[1002]; //ÈôÔªËØiÔÚ¼¯ºÏSÖУ¬ÔòsMem[i] = 1; ·ñÔòsMem = 0 
int sNum; //¼¯ºÏSÖÐÔªËصÄÊýÁ¿ 

long Dijkstra( int v0,int v1,int N ) ;

int main()
{
    int N , M , S , T ;
    int i , j , k ;
    long l ;
    scanf( "%d %d %d %d" , &N,&M,&S,&T ) ;
    
    for( i=1;i<=N;i++ )
    {
	    for( j=1;j<=N;j++ )
	    {
		    if(i==j)
		        map[i][j] = 0 ;
		    else
			    map[i][j] = 100000000 ;    
		}
	}
	
	i = 1 ;
	while( i<=M )
	{
	    i++ ;
	    scanf("%d %d %ld",&j,&k,&l) ;
	    
		if( map[j][k] > l )
		    map[j][k] = l ; 
	    if( map[k][j] > l )
	        map[k][j] = l ; 
	}
	
	
	printf("%ld\n",Dijkstra( S,T,N )) ;
	
	system("pause") ; 
    return 0 ;
}//int main()

long Dijkstra( int v0,int v1,int N )
{
    int i ; 
    int j ;
    long mindist ;
    int target ;
	
/*for( i=1 ; i<= 100 ; i++ )
	{
	    prev[i] = -1 ;
	}
	prev[v0] = 0 ;//³õʼ»¯Ç°Çý½ÚµãÊý×é 
*/
	
	for( i=1;i<=N;i++ )
    {
	    sMem[i] = 0 ;
	}
	sMem[v0] = 1 ; //³õʼ»¯¼Ç¼¼¯ºÏS 
	sNum = 1 ;//³õʼ»¯¼¯ºÏSÊýÁ¿
	
	for( i=1 ;i<=N; i++ ) 
	{
	    dist[i] = map[v0][i] ;
	}
	
	while(sNum<N)
	{
		mindist = 100000001 ;
	    for( i=1;i<=N;i++ )
	    {
		    if( (!(sMem[i])) && dist[i] < mindist )
		    {
			    target = i ; //iµãÊÇU¼¯ºÏÖоàÀëÔ­µã×î½üµÄµã 
			    mindist = dist[i] ;
			}
		}
        
		sMem[target] = 1 ;
		sNum++ ;
		
		for( i=1 ; i<=N ; i++ )
		{
		    if((!(sMem[i])) && (dist[i]>dist[target]+map[target][i]) )
		        dist[i] = dist[target]+map[target][i] ;
		}		
		
	}
	
	
	return dist[v1] ;
}//long Dijkstra( int v0,int v1,int N )

                                                                                                                                                                        

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值