4-5 单源最短路径 Dijikstra算法
一、问题描述
给定带权有向图G =(V,E),其中每条边的权是非负实数。V中的一个顶点,称为源。计算从源到所有其他各顶点的最短路径长度。
这个问题通常称为单源最短路径问题。路径长度是指路径上各边权之和。
二、基本思想
Dijkstra算法是解单源最短路径问题的贪心算法。
设置顶点集合S并不断地作贪心选择来扩充这个集合。一个顶点属于集合S当且仅当从源到该顶点的最短路径长度已知(贪心策略)。
初始时,S中仅含有源。
从源只经过S中顶点到达u( S外)称为从源到u的特殊路径,用数组dist记录当前每个顶点的最短特殊路径长度。最短特殊路径长度最小的为最短路径长度已知。
每次从V-S中取出最短路径长度已知的顶点u,将u添加到S中,同时对数组dist作必要的修改。直到S包含了所有V中顶点.
三、算法演示
另一道例题:
四、代码
#include<iostream>
using namespace std;
const int maxint=9999;
int c[100][100];
int dis[100],pre[100];//dis[i]记录i的最短路径; pre[i]=j,i的前一个顶点为j
void Dijkstra(int v,int n){//起始顶点为v
int i,j;
bool s[100];//判断是否已经找到最短路径
for(i=1;i<=n;i++){ //初始化
dis[i]=c[v][i];
s[i]=false;
if(dis[i]==maxint)
pre[i]=0;
else
pre[i]=v;
}
dis[v]=0;
s[v]=true; //将起点加入已找到最短路径的集合
for(i=1;i<=n;i++){
int t=maxint;
int u=v;
for(j=1;j<=n;j++){ //找到一个距离最小的顶点j,将j加入集合s
if(!s[j]&&dis[j]<t){
u=j;
t=dis[j];
}
}
s[u]=true;//将j加入集合s
for(j=1;j<=n;j++){ //更新其他点的距离
if(!s[j] && c[u][j]<maxint){
int newdis=dis[u]+c[u][j];
if(newdis<dis[j]){
dis[j]=newdis;
pre[j]=u;
}
}
}
}
}
int main(){
int m,n;//m条路线 n个顶点
int i,j,x,y,z;
cin>>m>>n;
for(i=1;i<=n;i++){ //初始化为最大值,不可达
dis[i]=maxint;
for(j=1;j<=n;j++){
c[i][j]=maxint;
}
}
for(i=1;i<=m;i++){
cin>>x>>y>>z;
c[x][y]=z;
}
Dijkstra(1,n); //1到各个顶点的最短路径
cout<<"输出pre--------------\n";
for(i=1;i<=n;i++)
cout<<pre[i]<<" ";
cout<<"\n输出dis--------------\n";
for(i=1;i<=n;i++)
cout<<dis[i]<<" ";
return 0;
}
五、运行截图
9 5
1 2 10
1 3 3
2 3 1
2 4 2
3 2 4
3 4 8
3 5 2
4 5 7
5 4 9
7 5
1 2 10
1 4 30
1 5 100
2 3 50
3 5 10
4 3 20
4 5 60