单源最短路径(Dijkstra算法)

原创 2013年12月04日 15:08:25

基本算法:

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


版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

单源最短路径:Dijkstra算法

单源最短路径:Dijkstra算法

Dijkstra---求单源最短路径(贪心算法)

算法步骤:1) Create a set sptSet (shortest path tree set) that keeps track of vertices included in shor...

贪心算法——单源最短路径 dijkstra

关于单源最短路径的问题非常典型,这里没有给出分析与证明,仅仅给出了实现。 需要指出的是,许多实现仅给出了最短路径的长度,而没有给出“最短路径”,这里用给出了实现。 如程序中那样,定义一个数...

POJ1062 昂贵的聘礼 单源最短路径变形 dijkstra算法

思路:以物品为结点,物品之间的优惠价格为边权值建图,酋长10000金币当做0号结点,题意就是求图中各结点到0号结点的最短路长度,再加上终点处物品的价值,恰好就是探险家经过这个物品买卖途径所需要付出的金...

单源最短路径---Dijkstra算法

基本模型 基本思想:每次找离源点最近的一个顶点,然后以改顶点为中心进行扩展,最终得到源点到其余所有点的最短路径。 具体步骤: 1. 将所有的顶点分为两个部分:已知最短路程的顶点集合P和未知最短路径...

单源最短路径_Dijkstra算法

题目:http://acm.hdu.edu.cn/showproblem.php?pid=3790 Problem Description 给你n个点,m条无向边,每条边都有长度d和花费p...

单源最短路径Dijkstra算法

Dijkstra算法中设置了一顶点集合S,从源点s到集合中的顶点的最终最短路径的权值均已确定。算法反复选择具有最短 路径估计的顶点u∈V - S,并将u加入S中,对u的所有出边进行松弛,在下列算法实...

[C++]C++ STL Dijkstra算法 带权有向图(邻接表)单源最短路径求解

单源最短路径问题求解带权有向图(邻接表表示法)完整源码#include #include #include #include using namespace std;map<int , vec...

Dijkstra算法实现有向图单源最短路径

给定一个带权有向图G=(V,E),其中每条边的权都是非负实数。另外,还给定V中的一个顶点,称为源,现在要求解的是从源到其他所有顶点的最短路长度,即所经过路径的权的和,这就是所谓的单源最短路径问题。  ...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)