Dijkstra(迪杰斯特拉)算法是典型的最短路径路由算法,用于计算一个节点到其他所有节点的最短路径。主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。Dijkstra算法能得出最短路径的最优解,但由于它遍历计算的节点很多,所以效率低。
其基本思想是,设置顶点集合S并不断地作贪心选择来扩充这个集合。一个顶点属于集合S当且仅当从源到该顶点的最短路径长度已知。
初始时,S中仅含有源。设u是G的某一个顶点,把从源到u且中间只经过S中顶点的路称为从源到u的特殊路径,并用数组dist记录当前每个顶点所对应的最短特殊路径长度。Dijkstra算法每次从V-S中取出具有最短特殊路长度的顶点u,将u添加到S中,同时对数组dist作必要的修改。一旦S包含了所有V中顶点,dist就记录了从源到所有其它顶点之间的最短路径长度。
算法步骤:
1) 找到o到P中各点的最小值,经过查找o—x最小;
2) 找S中第一个点s0到集合P中所有点的最短距离,经过查找s0—px0最小,那么我们找S中第二个点s1集合P中所有点的最短距离,经过查找s1—px1最小,如此下去,直至我们找到了集合S中最后一个元素sn到P中所有点最短距离sn—pxm,这时我们需要找到o—s0—px0, o—s1—px1……o—sn—pxm中最短的一个o—si—pxj;
3) 比较o—x,o—si—pxj两条路径,如果前者更小则将x从P中剔除掉并纳入S中,如果后者更小则将pxj从P中剔除掉并纳入到S中,假设纳入到S中这个点位y,记录o—y的最小值,共以后计算使用;
4) 这一步我们要判断P是否为空集,如果P为空集算法结束,如果P中还有元素,重复上边三步。
#include<iostream>
#include<stdio.h>
#include<string.h>
#define N 100000000
using namespace std;
int dist[205]; //记录源点到每个结点的最短路径
int map[205][205];
bool visit[205]; //定义访问过的结点
int n,m;
void init() //init 通常做为 initialization 的缩写使用。即:设定初值,初始化的意思
{
int i,j;
for( i=0; i<n; i++){
for( j=0; j<n; j++)
map[i][j]=N;
dist[i]=N;
visit[i]=false;
}
}
bool Dijkstra(int s,int t) //s,t分别表示一个点到另一个点
{
int mim,k,i;
dist[s]=0; //该点到该点的最短路径为0
k=s;
memset(visit,false,sizeof(visit));
while( true){
visit[k]=true;
if( k==t) //如果访问到所求点,跳出
break;
for( i=0; i<n; i++)
if( !visit[i]&&map[k][i]!=N) //如果该节点没有被访问过 并且 该节点和源点连通
dist[i]=min(dist[i],dist[k]+map[k][i]); // 求与源点连通的点中 与源点距离最短的点
mim=N;
k=-1;
for( i=0; i<n; i++){
if( !visit[i]&&mim>dist[i]){ //如果该点存在且最小
mim=dist[i];
k=i; //变换下一个结点为k=i;
}
}
if( k==-1) break; //如果不存在符合要求的与当前结点 相连的点 跳出 结束
}
return k==t ? dist[t] :false; //找到所求的点输出记录的最短距离 dist[t] 否则输出错误
}
int main()
{
int s,t,i,j,x;
while( scanf("%d%d",&n,&m)!=EOF){
init();//初始化
while( m--){
scanf("%d%d%d",&i,&j,&x);
if( x<map[i][j]) //相连通的点重新赋值
map[i][j]=map[j][i]=x;
}
scanf("%d%d",&s,&t);
printf("%d\n",Dijkstra(s,t));
}
return 0;
}