关闭

单源最短路径(Dijkstra算法)

874人阅读 评论(1) 收藏 举报
分类:

基本算法:

将图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


0
0

猜你在找
【直播】机器学习&数据挖掘7周实训--韦玮
【套餐】系统集成项目管理工程师顺利通关--徐朋
【直播】3小时掌握Docker最佳实战-徐西宁
【套餐】机器学习系列套餐(算法+实战)--唐宇迪
【直播】计算机视觉原理及实战--屈教授
【套餐】微信订阅号+服务号Java版 v2.0--翟东平
【直播】机器学习之矩阵--黄博士
【套餐】微信订阅号+服务号Java版 v2.0--翟东平
【直播】机器学习之凸优化--马博士
【套餐】Javascript 设计模式实战--曾亮
查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:71266次
    • 积分:1398
    • 等级:
    • 排名:千里之外
    • 原创:64篇
    • 转载:1篇
    • 译文:2篇
    • 评论:24条
    最新评论