关于本题的floyd解法:http://blog.csdn.net/sm9sun/article/details/53282826
上篇博文介绍了floyd解决最短路径的方法,然而由于floyd极大的时间开销O(n^3)导致其应用领域并不是很广
本文再介绍一个最短路径的算法——Dijkstra算法
Dijkstra算法是典型的算法。Dijkstra算法是很有代表性的算法。Dijkstra一般的表述通常有两种方式,一种用永久和临时标号方式,一种是用OPEN, CLOSE表的方式,这里均采用永久和临时标号的方式。注意该算法要求图中不存在负权边。Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径。主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。
首先,引进一个辅助向量D,它的每个分量D表示当前所找到的从始点v到每个终点vi的最短路径的长度。如D[3]=2表示从始点v到终点3的路径相对最小长度为2。这里强调相对就是说在算法过程中D的值是在不断逼近最终结果但在过程中不一定就等于最短路径长度。它的初始状态为:若从v到vi有弧,则D为弧上的权值;否则置D为∞。显然,长度为 D[j]=Min{D | vi∈V} 的路径就是从v出发的长度最短的一条最短路径。此路径为(v,vj)。 那么,下一条长度次短的最短路径是哪一条呢?假设该次短路径的终点是vk,则可想而知,这条路径或者是(v,vk),或者是(v,vj,vk)。它的长度或者是从v到vk的弧上的权值,或者是D[j]和从vj到vk的弧上的权值之和。 一般情况下,假设S为已求得最短路径的终点的集合,则可证明:下一条最短路径(设其终点为X)或者是弧(v,x),或者是中间只经过S中的顶点而最后到达顶点X的路径。因此,下一条长度次短的最短路径的长度必是D[j]=Min{D | vi∈V-S} 其中,D或者是弧(v,vi)上的权值,或者是D[k](vk∈S)和弧(vk,vi)上的权值之和。迪杰斯特拉算法描述如下: 1)arcs表示弧上的权值。若不存在,则置arcs为∞(在本程序中为MAXCOST)。S为已找到从v出发的最短路径的终点的集合,初始状态为空集。那么,从v出发到图上其余各顶点vi可能达到的最短路径长度的初值为D=arcs[Locate Vex(G,v),i] vi∈V 2)选择vj,使得D[j]=Min{D | vi∈V-S} 3)修改从v出发到集合V-S上任一顶点vk可达的最短路径长度。
以上为百科对于Dijkstra的描述,其实通俗一点说,就是先采取贪心的思路,先选择一个接下来准备连接的权值最小的点j,然后看看是否存在某个k点,满足到j再到k的值要小于直接到k本身,如果有,优化路径。看起来原理差不太多,Dijkstra是贪心的一个一个节点添加,加一个点刷一次路径。。而floyd是把所有已经连接的路径都标出来,再通过不等式比较来优化路径。
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=2112
题目描述:
经过锦囊相助,海东集团终于度过了危机,从此,HDU的发展就一直顺风顺水,到了2050年,集团已经相当规模了,据说进入了钱江肉丝经济开发区500强。这时候,XHD夫妇也退居了二线,并在风景秀美的诸暨市浬浦镇陶姚村买了个房子,开始安度晚年了。
这样住了一段时间,徐总对当地的交通还是不太了解。有时很郁闷,想去一个地方又不知道应该乘什么公交车,在什么地方转车,在什么地方下车(其实徐总自己有车,却一定要与民同乐,这就是徐总的性格)。
徐总经常会问蹩脚的英文问路:“Can you help me?”。看着他那迷茫而又无助的眼神,热心的你能帮帮他吗?
请帮助他用最短的时间到达目的地(假设每一路公交车都只在起点站和终点站停,而且随时都会开)。
Input
输入数据有多组,每组的第一行是公交车的总数N(0<=N<=10000);
第二行有徐总的所在地start,他的目的地end;
接着有n行,每行有站名s,站名e,以及从s到e的时间整数t(0<t<100)(每个地名是一个长度不超过30的字符串)。
note:一组数据中地名数不会超过150个。
如果N==-1,表示输入结束。
Output
如果徐总能到达目的地,输出最短的时间;否则,输出“-1”。
Sample Input
6
xiasha westlake
xiasha station 60
xiasha ShoppingCenterofHangZhou 30
station westlake 20
ShoppingCenterofHangZhou supermarket 10
xiasha supermarket 50
supermarket westlake 10
-1
Sample Output
50
Hint:
The best route is:
xiasha->ShoppingCenterofHangZhou->supermarket->westlake
#include<stdio.h>
#include<string.h>
#define INF 999999999
int V_nMapValue[155][155];
int C_nPointId;
char N_sPointName[155][40];
int fmin(int a,int b)
{
return a<b?a:b;
}
void Init()
{
int i,j;
for(i=0;i<155;i++)
for(j=0;j<155;j++)
V_nMapValue[i][j]=(i==j)?0:INF;
}
int Get_PointId_by_PointName(char *s)
{
int i;
for(i=0;i<C_nPointId;i++)
if(!strcmp(N_sPointName[i], s))
return i;
strcpy(N_sPointName[C_nPointId],s);
C_nPointId++;
return C_nPointId-1;
}
void Dijkstra()
{
int Z_vis[155], i,j,k;
memset(Z_vis, 0, sizeof(Z_vis));
for(i=0;i<C_nPointId;i++)
{
int Id_temp=0,Value_temp=INF;
for(j=0;j<C_nPointId;j++) //最短连接点
if(!Z_vis[j]&&V_nMapValue[0][j]<Value_temp)
{
Id_temp=j;
Value_temp=V_nMapValue[0][j];
}
if(Value_temp==INF) //没有合适的新路径
break;
Z_vis[Id_temp]=1; //选入新点
for(k=0;k<C_nPointId;k++) //优化路径
V_nMapValue[0][k]=fmin(V_nMapValue[0][k],V_nMapValue[0][Id_temp]+V_nMapValue[Id_temp][k]);
}
}
void Floyd()
{
int i,j,k;
//存在一个k 使aik+akj路径小于aij
for(k=0;k<C_nPointId;k++)
for(i=0;i<C_nPointId;i++)
for(j=0;j<C_nPointId;j++)
V_nMapValue[i][j]=fmin(V_nMapValue[i][j],V_nMapValue[i][k]+V_nMapValue[k][j]);
}
int main()
{
int n,i,j;
while(~scanf("%d",&n)&&n!=-1)
{
Init();
char N_sStPoint[40], N_sEnPoint[40];
scanf("%s%s",&N_sStPoint, &N_sEnPoint);
strcpy(N_sPointName[0], N_sStPoint);
strcpy(N_sPointName[1], N_sEnPoint);
C_nPointId = 2;
char Point_a_name[40],Point_b_name[40];
int Point_a_id,Point_b_id,Value_By_ab;
for(i=0;i<n;i++)
{
scanf("%s%s%d",&Point_a_name,&Point_b_name,&Value_By_ab);
Point_a_id = Get_PointId_by_PointName(Point_a_name);
Point_b_id = Get_PointId_by_PointName(Point_b_name);
V_nMapValue[Point_a_id][Point_b_id] = V_nMapValue[Point_b_id][Point_a_id] = Value_By_ab;
}
if(!strcmp(N_sStPoint, N_sEnPoint))
{
printf("0\n");
continue;
}
/*
for(i=0;i<C_nPointId;i++)
for(j=0;j<C_nPointId;j++)
printf("%d%c",V_nMapValue[i][j],j==C_nPointId-1?'\n':' ');
*/
Dijkstra();
//Floyd();
if(V_nMapValue[0][1]==INF)
printf("-1\n");
else
printf("%d\n",V_nMapValue[0][1]);
}
return 0;
}