单源最短路径(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算法是解单源最短路径问题的贪心算法。其基本思想是,设置顶点集合点集合S并不断地做贪心选择来扩充这个集合。一个顶点属于集合S当且仅当从源到该顶点的最短路径长度已知。初始时,S中仅含有源。...

单源最短路径—Dijkstra算法(C++)

最近复习图算法,练练手 先拿Dijkstra算法开刀吧以下是C++代码包含:Dijkstra算法函数(返回源节点到其余节点之间的最短路径)、路径打印输出函数PS:本人只喜欢用vector,不喜欢用原...

带权有向图单源最短路径(Dijkstra算法)

单源最短路径问题,即在图中求出给定顶点到其它任一顶点的最短路径。在弄清楚如何求算单源最短路径问题之前,必须弄清楚最短路径的最优子结构性质。 一.最短路径的最优子结构性质 该性质描述为:如果P(i,j)...
  • arhaiyun
  • arhaiyun
  • 2013年09月30日 01:17
  • 11019

Dijkstra算法求单源最短路径(二)(BFS的改版)

1.解析该算法其实就是广度优先算法的改版,只是将广度优先算法中的普通队列改为了这里的优先队列。2.算法实例#include #include #include #include #...

数据结构:单源最短路径--Dijkstra算法

单源最短路径 给定一带权图,图中每条边的权值是非负的,代表着两顶点之间的距离。指定图中的一顶点为源点,找出源点到其它顶点的最短路径和其长度的问题,即是单源最短路径问题。 Dijkstra算法...

单源最短路径的迪克斯特拉(Dijkstra)算法

#include #include #include #define MAXV 100 #define LIMITLESS 9999 //定义为无穷大,默认为节点间不存在联系 using na...
  • lfb637
  • lfb637
  • 2017年12月09日 11:36
  • 17

Dijkstra算法(单源最短路径)

模板 #include   #include #define MAX 201 #define INF 100000 int map[MAX][MAX]; int min[MAX];...
  • ymmqwe
  • ymmqwe
  • 2014年03月13日 14:14
  • 350

单源最短路径(Dijkstra算法)

单源最短路径问题,给定带权有向图G和源点v,求从v到G中其余各顶点的最短路径。  可以到达的点填权值 否则为无限大 1.先找出v0到各顶点中的当前未找到最短路径的顶点vi的最短的权值(也就...
  • yf224
  • yf224
  • 2017年05月23日 22:31
  • 88

DijKstra算法(单源最短路径)

原文转载自:梦醒潇湘love 转载原文是为了方便自己学习,也希望能让更多读者在需要的情况下学到更多的知识。       Dijkstra(迪杰斯特拉)算法是典型的最短路径路由算法,用于计算一个...

Dijkstra算法求单源最短路径

当我想通了 Dijkstra 算法的时候,我和我的小伙伴们都惊呆了O(∩_∩)O~
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:单源最短路径(Dijkstra算法)
举报原因:
原因补充:

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