基本算法:
将图G中所有的顶点V分成两个顶点集合Va和Vb,如果源点S到u的最短路径已经确定,则点u属于集合Va,否则属于集合Vb。最开始的时候Va只包含源点S,其余的点属于Vb,
算法结束时所有由源点可达的点属于Va,不可达的点仍属于Vb。可以在求出最短路径长的同时记录最短路径,方法是记录终点前的前一个点,这样倒着查回去就能确定整条最短路径。
具体步骤:
(1)首先初始化,将源点S到图中各点的直接距离当作初始值记录为S到各点的最短距离,如果不能直接到达,记为INF_MAX,S到S的距离为0.
( 2)在所有属于Vb的点中找一个S到其路径长度最短的点u,将u从Vb中除去,加入到Va,既当前求出的S到u的路径为S到u的最短路径
(3)有新确定的u点更新S到Vb中每一点v的距离,如果S到u的距离加上u到v的直接距离小于当前S到v的距离,表明新生成的最短路径长度要比前面计算的更短,那么就更新这个距离,同时更新最短路径。
(4)重复步骤(2)(3)的过程,直到Vb中已经没有点或者Vb中的点都不能由源点S到达;
#include<iostream>
#include<stack>
using namespace std;
#define LEN 201
int map[LEN][LEN];//邻接矩阵
int *dist; //记录当前点到源点的最短路径
int *pre;//记录前驱,源点,终点
//***********************************************************************
void dijkstra(int n,int s)
{
int i,j,k;
int min;
bool p[LEN]; //记录该点是否属于Va,否则属于Vb,当=false时属于Vb;
for(i=1;i<=n;i++)
{
p[i]=false; //初始化全都属于Vb
if(i!=s)
{
dist[i]=map[s][i]; //记录直接与源点的距离
pre[i]=s; //前驱为源点
}
}
dist[s]=0;//源点到源点的距离为0
p[s]=true;
for(i=1;i<=n-1;i++) //循环n-1次,求源点到其他n-1个点的最短路径
{
min=INT_MAX;
k=0;
for(j=1;j<=n;j++)
if(!p[j]&&dist[j]<min)//在Vb中的点中取一源点到其距离最小的点的路径
{
min=dist[j];
k=j;
}
if(k==0) return ; //如果没有点可以扩展,即剩余的点不可达,返回
p[k]=true; //将k从Vb中除去,添加到Va中
for(j=1;j<=n;j++) //对于每个与k相邻的在Vb中的点j,更新源点到j的最短路径
if(!p[j] && map[k][j]!=INT_MAX&&dist[j]>dist[k]+map[k][j])
{
dist[j]=dist[k]+map[k][j];
pre[j]=k;
}
}
}
//***********************************************************************
void showpre(int *pre,int v,int v0) //打印最短路径上的各个顶点
{
stack<int> s;
while(v!=v0)
{
s.push(v);
v=pre[v];
}
s.push(v);
while(!s.empty())
{
cout<<s.top()<<" ";
s.pop();
}
}
//***********************************************************************
int main()
{
int n,m;//n个顶点,m条边
int start,end,val;
cin>>n>>m;
dist=(int *)malloc(sizeof(int)*n); //动态分配内存,免得浪费空间
pre=(int *)malloc(sizeof(int)*m);
//初始化邻接矩阵
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
map[i][j]=INT_MAX;
for(i=0;i<m;i++)
{
cin>>start>>end>>val;
map[start][end]=val;
}
dijkstra(n,1);//1表示源点为1,源点自己定义
showpre(pre,5,1);
cout<<dist[5]<<endl;//输出源点到5的最短路径
showpre(pre,4,1);
cout<<dist[4]<<endl;//输出源点到4的最短路径
return 0;
}
测试数据:5 7
1 2 10
1 4 30
1 5 100
2 3 50
3 5 10
4 3 20
4 5 60