图——最短路径(Dijkstra)

本文详细介绍了一种求解图中单源最短路径问题的经典算法——Dijkstra算法,并提供了详细的算法步骤及C++代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

求图的最短路径问题又分为两个方面:

(1)一个顶点到其余各顶点的最短路径;(本文介绍)

(2)图中每对顶点之间的最短路径。

1、一个顶点到其余个顶点的最短路径

给定一个带权有向图G与源点v,求顶点v到G中其余各顶点的最短路径。(限定不存在权值为负的边)

Dijkstra基本思想:将图中所有顶点分为两个集合S与U。S中包含所有已经找到最短路径的顶点,初始时S中只包含源点v。U中包含未找到最短路径的顶点,初始时包含除源点v以外的其余顶点。之后,每找到一条最短路径v--->k,就将k加入集合S中,直至所有顶点都加入到S中。

Dijkstra算法步骤:

(1)以v为源点,找到v到其余个顶点的距离;

         若v--->k之间存在边,则将边<v,k>的权值作为v,k之间的距离;

         若v--->之间不存在边,则将边<v,k>之间的距离设为∞;

(2)从U 中选出u,v--->u是距离最小的边,将顶点u加入到S中;

(3)以u为中间节点,更新v到其余各顶点的距离;

(4)重复(2)、(3),直至所有的顶点都以已加入S中。

Dijkstra代码实现:

#include<cstdio>
#define INF 32767
using namespace std;

const int MAXV = 100;
int edges[MAXV][MAXV];
struct MGraph{
	int n;
	int e;
	int edges[MAXV][MAXV];
};

void createMGraph(MGraph &g){
	int i,j;
	int a,b,w;
	scanf("%d%d",&g.n,&g.e);
	//初始化
	for(i=0;i<g.n;i++)
		for(j=0;j<g.n;j++){
			if(i==j)
				g.edges[i][j] = 0;
			else
				g.edges[i][j] = INF;
		}
		
	for(i=0;i<g.e;i++){
		scanf("%d%d%d",&a,&b,&w);
		g.edges[a][b] = w;	
	}	
} 

void Dispath(MGraph g,int dist[],int path[],int s[],int v){
	int i,j,k;
	int apath[MAXV],d;               //存放一条最短路径(逆向)以及顶点个数 
	for(i=1;i<=g.n;i++){
		if(s[i]!=0 && i!=v){
			printf("%d---%d的最短路径为:%d\t路径为",v,i,dist[i]);
			d =0;apath[d] = i;      //添加路径上的终点 
			k = path[i];
			if(k==-1)              //无路径的情况 
				printf("无路径\n");
			else
			{
				while(k!=v){       //存在路径是输出该路径 
					d++,apath[d]=k;
					k = path[k];
				}
				d++;apath[d]=v;           //添加起点 
				printf("%d",apath[d]);    //先输出起点 
				for(j=d-1;j>=0;j--)       //再输出其他顶点 
					printf(" ,%d",apath[j]);
				printf("\n");
			}
		}
	}
}

void Dijkstra(MGraph g,int v){
	int dist[MAXV],path[MAXV];
	int s[MAXV];
	int mindis,i,j,u;
	
	for(i=0;i<g.n;i++){                     //步骤(1),初始化dist[],path[],s[] 
		dist[i] = g.edges[v][i];
		s[i] = 0;
		if(g.edges[v][i]<INF)
			path[i] = v;
		else
			path[i] = -1;
	}
	s[v] = 1;path[v] = v;
	
	for(i=0;i<g.n;i++){
		mindis = INF;
		for(j=0;j<g.n;j++)                  //步骤(2)遍历边,找到最短的,将顶点u加入S中 
			if(s[j]==0 && dist[j]<mindis){  
				u = j;
				mindis = dist[j];
			}
		s[u] = 1;
		for(j=0;j<g.n;j++)        //步骤(3)以u为中间节点,更新v到U中各点的距离 
			if(s[j]==0)
				if(g.edges[u][j]<INF && dist[u]+g.edges[u][j]<dist[j]){//如果v--->u--->j的距离小于 v--->j的距离,则更新 
					dist[j] = dist[u]+g.edges[u][j];
					path[j] = u;
				}
	}
	Dispath(g,dist,path,s,v); 
}

int main(){
	MGraph g;
	createMGraph(g);
	Dijkstra(g,0);
	return 0;
} 
/*
7 12
0 1 4
0 2 6
0 3 6
2 4 6
2 5 4
1 4 7
1 2 1
3 2 2
3 5 5
4 6 6
5 4 1
5 6 8
*/

运行结果:







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值