基于C++的Dijkstra最短路径算法

#include "stdafx.h"
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<iostream>
#include<functional>
using namespace std;
const int maxn = 1e3;
const int INF = 1e9;
//int G[maxn][maxn];//邻接表表示
int dis[maxn];//最短路
int vis[maxn] = { false };//标记顶点v是否已被访问
int vertex, edge, start;//顶点,边,起点
int pre[maxn];//pre[i]=u代表结点i的前驱为u
int num[maxn] = { 0 };//记录最短路径条数
struct node{
	int v;
	int routelen;
};
vector<node> adjacent[maxn];//邻接矩阵表示
void dijkstra(int start) {//Dijkstra算法
	fill(dis, dis + maxn, INF);//最短路径初始化为无穷
	fill(pre, pre + maxn, -1);//初始化前驱
	dis[start] = 0;
	pre[start] = start;
	num[start] = 1;
	for (int i = 0; i < vertex; i++) {//循环n次
		int u = -1, min = INF;
		for (int j = 0; j < vertex; j++) {//寻找还未被访问顶点的最短路
			if (dis[j] < min && vis[j] == false) {
				u = j;
				min = dis[j];
			}
		}
		if (u == -1) return;//如果没找到,则return
		vis[u] = true;//如果找到,则置u被访问
		for (int j = 0; j < adjacent[u].size(); j++) {//从u出发能够到达的所有顶点
			int v = adjacent[u][j].v;
			if (vis[v] == false) {
				if (dis[u] + adjacent[u][j].routelen < dis[v]) {//v未被访问&&以u为中介点能够使得dis[v]更短
					dis[v] = dis[u] + adjacent[u][j].routelen;//更新路径
					pre[v] = u;//更新前驱
					num[v] = num[u];//更新路径条数
				}
				else if (dis[u] + adjacent[u][j].routelen == dis[v]) {//此处一定要用else if语句,不能用if,否则得到的num不正确
					num[v] += num[u];//更新路径条数
				}
			}
		}
	}
}
void dfs(int a[],int k) {//递归输出最短路径
	if (a[k] == k) {
		printf("%d", k);
	}
	else if (a[k] == -1) {
		printf("无到达此点的路径");
	}
	else {
		dfs(a, a[k]);//递归输出前驱结点
		printf("->%d", k);//输出本结点
	}
}
int main() {
	//fill(G[0], G[0] + maxn * maxn, INF);
	scanf("%d%d%d", &vertex, &edge, &start);
	int s, e, value;
	for (int i = 0; i < edge; i++) {
		int start, end, weight;
		scanf("%d%d%d", &start, &end, &weight);//分别输入起点,终点,边权
		node V;
		V.v = end;//v是边的目标顶点
		V.routelen = weight;//边权
		adjacent[start].push_back(V);
	}
	dijkstra(start);
	for (int i = 0; i < vertex; i++) {//输出以start为源点,到达各大顶点的最短距离
		printf("%d ", dis[i]);
	}
	putchar('\n');
	int k;
	scanf("%d", &k);//输入目标顶点k
	dfs(pre, k);//输出源点到目标顶点k的最短路径
	printf("\n%d", num[k]);//输出源点到目标顶点的最短路径条数
	return 0;
}

运行结果如下:

《基于C++的Dijkstra最短路径算法》

《基于C++的Dijkstra最短路径算法》

注意:Dijkstra最短路经算法的时间复杂度主要是由外层循环O(V)和内层循环寻找最小的d(U)需要的O(V)、枚举V需要的O(adjacent[U].size)产生的,所以时间复杂度是O(V方+E),现在采用堆进行优化(最简洁的做法就是采用STL库里的优先队列进行优化),使复杂度降为O(vlogv+E),即O(vlogv)

当然,采用邻接表的话,时间复杂度达到了O(V方)

Dijkstra是用来求解无负权图的单源最短路径问题。如果要求解带有负权图的单源最短路径,则需要采用Bellman-Ford或SPFA算法,Bellman-Ford算法讲解请看下节:

    原文作者:Dijkstra算法
    原文地址: https://blog.csdn.net/qq_39034748/article/details/80996017
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞