单源最短路径(Dijkstra算法)

来源:互联网 发布:忧伤的嫖客知乎 编辑:程序博客网 时间:2024/05/22 05:23

基本算法:

将图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 201int 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;   //初始化全都属于Vbif(i!=s){dist[i]=map[s][i];  //记录直接与源点的距离pre[i]=s;   //前驱为源点}}dist[s]=0;//源点到源点的距离为0p[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


原创粉丝点击