最短路径:在一个图中,如果从一顶点到另一顶点存在着路径,那么定义路径长度为一条路径上所经过的边的数目,那么这个图中从一顶点到另一顶点的所有路径中路径长度最短的叫做最短路径;在一个带权图中,权路径长度最小的叫做最短路径,其带权路径长度叫做最短路径长度(迪杰斯特拉主要求带权图的最短长度)
迪杰斯特拉的算法思想:
对于有向带权图中从一确定顶点到其余各点的最短路径问题:
首先,设置两个顶点集合S和T,集合S中存放已找到最短路径的顶点,集合T用来存放当前还未找到最短路径的顶点。刚开始集合S中只有源点(即起点),设为 v0,然后从集合T中
选到源点最短路径的顶点 u 加入到集合S中,集合S中每加入一个新的顶点u,都要修改源点到集合T中剩余顶点的当前最短路径的长度值,集合T各顶点新的当前最短路径的长度值
为原来的当前最短路径与从源点过顶点u到达该顶点路径长度的较小者,此过程不断重复,直到所有顶点都加入集合S为止。
迪杰斯特拉的模板;
(1)
首先,定义一个数组 dis[](用来放源点到各顶点的最短路径长度)和数组vis[] (用来标记已找到从顶点u到原点的最短路径),INF = oxffffffff;
n为顶点个数,map[][]用来存放图
void dijkstra( int s ) //s为源点
{
int i , j, u , v;
for(i = 1; i < =n ; i++ ) { //初始化
dis [i] = INF;
vis [i] = 0;
}
dis [s] = 0; //源点到其自身的距离为零
while(1){
v=-1;
for(u = 1;u < = n;u + + ) {
if ( ! vis[u] && ( v = = -1||dis [u] <= dis [v]))
v=u;
}
if ( v = ==-1) //当所有顶点都放入集合S后,v的值就不会变(v= = -1)跳出循环
break;
for (u = 1;u< =n;u + +){
dis[u] = min ( dis [u], dis [v] +map [v][u]); //min 是事先定义好的求最小值函数;
}
}
(2)第二种模板:(以hdu2544最短路为例)
#include<stdio.h>
#include<string.h>
#define INF 0xfffff
int map[1010][1010],vis[120],d[120];
int n,m;
void dijkstra(int s){
int i,j,k,min;
for(i = 1;i< = n;i++){ //初始化
d[i] = map[s][i];
vis[i] = 0;
}
d[s] = 0; //源点到自身的距离为零
vis[s] = 1; // 标记源点,表示已放入集合S;
for(i = 1;i < n;i++){ //开始主循环,每次求的v0到各顶点v的最短距离;
min = INF;
for(j = 1;j < = n;j++){
if(! vis[j]&&(min > d[j])){
k = j;
min = d[j];
}
}
vis[k] = 1;
for(j = 1;j < = n;j++){
if(!vis[j]&&(d[j] > (min+map[k][j])))
d[j] = min+map[k][j];
}
}
}
int main()
{
int i,j,k,a,b,c;
while(scanf("%d%d",& n,& m)&&(n|m)){
for(i=1;i< = n;i++)
for(j = 1;j < = n;j++)
map[i][j] = INF;
for(i = 1;i < = m;i++){
scanf("%d%d%d",&a,&b,&c);
map[a][b] = map[b][a] = c;
}
dijkstra(1);
printf("%d\n",d[n]);
}
return 0;
}