迪杰斯特拉算法实例演示(Dijkstra)

一.题目(牛客)

题目描述:旅行者的地图给出了高速公路沿线城市之间的距离以及每条高速公路的成本。
现在你应该写一个程序来帮助旅行者决定他/她的起始城市和目的地之间的最短路径。
如果这样的最短路径不是唯一的,那么您应该输出具有最小成本的路径,这保证是唯一的。

每个输入文件包含一个测试用例。每个案例都以包含4个正整数N,M,S和D的行开头,其中N(<= 500)是城市的数量(因此城市的编号从0到N-1); M是高速公路的数量; S和D分别是起始城市和目的地城市。然后M行跟随,每个都提供高速公路的信息,格式为:
City1 City2 Distance Cost ,
其中数字全部不超过500,并用空格分隔。

输入描述:对于每个测试用例,沿着从起点到目的地的最短路径沿城市打印一行,然后是总距离和路径的总成本。数字必须用空格分隔,输出结尾必须没有多余的空格。

输出描述:对于每个测试用例,沿着从起点到目的地的最短路径沿城市打印一行,然后是总距离和路径的总成本。数字必须用空格分隔,输出结尾必须没有多余的空格。

输入样例
4 5 0 3 0 1 1 20 1 3 2 30 0 3 4 10 0 2 2 20 2 3 1 20
输出样例
0 2 3 3 40

二.解题思路

使用邻接矩阵作为数据存储结构,用迪杰斯特拉算法求解最短路径

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
int const MaxVreterNum = 500;
#define INFINITY  65535
typedef int Vertex;
typedef int WeightType;

struct Enode {//边的定义
	Vertex v1, v2;
	WeightType Weight;
	WeightType Money;
};
typedef Enode *Edge;

struct Gnode {//图,列矩阵
	int NumVex;
	int NumEdge;
	WeightType G[MaxVreterNum][MaxVreterNum];
	WeightType M[MaxVreterNum][MaxVreterNum];
};
typedef Gnode *MGraph;

MGraph CreatGraph(int VertexNum);
void InsertEdge(MGraph Graph, Edge E);
MGraph BuildGraph(Vertex &S, Vertex &D);
Vertex FindMinDist(MGraph Graph, int dist[], int collected[]);
bool Dijkstra(MGraph Graph, int dist[], int path[], int cost[], Vertex S);
void FindThePathOut(MGraph Graph, Vertex S, Vertex D);

int main()
{
	MGraph Graph;
	Vertex S, D;
	Graph = BuildGraph(S, D);
	FindThePathOut(Graph, S, D);
	return 0;
}
MGraph CreatGraph(int VertexNum)
{
	MGraph Graph;
	Graph = new Gnode;
	Graph->NumVex = VertexNum;
	Graph->NumEdge = 0;
	for (Vertex v = 0; v < Graph->NumVex; v++)
	{
		for (Vertex w = 0; w < Graph->NumVex; ++w)
		{
			Graph->G[v][w] = INFINITY;
			Graph->M[v][w] = INFINITY;
		}
	}
	return Graph;
}
void InsertEdge(MGraph Graph, Edge E)
{//插入边
	Graph->G[E->v1][E->v2] = E->Weight;
	Graph->G[E->v2][E->v1] = E->Weight;
	Graph->M[E->v1][E->v2] = E->Money;
	Graph->M[E->v2][E->v1] = E->Money;
}
MGraph BuildGraph(Vertex &S, Vertex &D)
{//创建图
	MGraph Graph;
	Edge E;
	Vertex NumVex;
	cin >> NumVex;
	Graph = CreatGraph(NumVex);
	cin >> Graph->NumEdge >> S >> D;
	if (Graph->NumEdge != 0)
	{
		E = new Enode;
		for (int i = 0; i < Graph->NumEdge; i++)
		{
			cin >> E->v1 >> E->v2 >> E->Weight >> E->Money;
			InsertEdge(Graph, E);
		}
	}
	return Graph;
}
/*迪杰斯特拉算法描述:以每一个顶点为源点,重复执行迪杰斯特拉算法n次,即可求出每一对顶点之间的最短路径;
迪杰斯特拉算法主要分为三步
1.创建数据存储结构(此处为邻接矩阵)
2.函数FindMinDist()找到当前为访问顶点的最短路径;
3.此处使用栈存储,输出从目的地到出发点的最短路径;
*/
bool Dijkstra(MGraph Graph, int dist[], int path[], int cost[], Vertex S)
{
	int collected[Graph->NumVex];
	Vertex V;
	for (V = 0; V < Graph->NumVex; ++V)
	{
		dist[V] = Graph->G[S][V];
		cost[V] = Graph->M[S][V];
		path[V] = S;
		collected[V] = false;
	}
	dist[S] = 0;
	cost[S] = 0;
	collected[S] = true;
	while (true)
	{
		V = FindMinDist(Graph, dist, collected);
		if (V == -1)
			break;
        collected[V] = true;
		for (Vertex W = 0; W < Graph->NumVex; ++W)
		{
			if (collected[W] == false && Graph->G[V][W] < INFINITY)
			{
				if (Graph->G[V][W] < 0)
					return false;
				if (dist[V] + Graph->G[V][W] < dist[W])
				{
					dist[W] = dist[V] + Graph->G[V][W];
					path[W] = V;
					cost[W] = cost[V] + Graph->M[V][W];
				}
				else if (dist[V] + Graph->G[V][W] == dist[W] && cost[V] + Graph->M[V][W] < cost[W])
				{
					dist[W] = dist[V] + Graph->G[V][W];
					path[W] = V;
					cost[W] = cost[V] + Graph->M[V][W];
				}
			}
		}
	}
    return true;
}
Vertex FindMinDist(MGraph Graph, int dist[], int collected[])
{//在数据中寻找当前最短
	Vertex MinVex = 0;
	int MinDist = INFINITY;
	for (Vertex V = 0; V < Graph->NumVex; V++)
	{
		if (collected[V] == false && dist[V] < MinDist)
		{
			MinDist = dist[V];
			MinVex = V;
		}
	}
	if (MinDist < INFINITY)
	{
		return MinVex;
	}
	else
		return -1;
}
void FindThePathOut(MGraph Graph, Vertex S, Vertex D)
{//打印最短路径
	int dist[Graph->NumVex];
    int path[Graph->NumVex];
    int cost[Graph->NumVex];
	Dijkstra(Graph, dist, path, cost, S);
	vector<Vertex> ThePath;
	Vertex P = D;
	ThePath.push_back(P);
	while (P != S)
	{
		ThePath.push_back(path[P]);
		P = path[P];
	}
	for (auto it = ThePath.rbegin(); it != ThePath.rend(); ++it)
		cout << *it << " ";
	cout << dist[D] << " " << cost[D] << endl;
}

迪杰斯特拉算法Dijkstra's algorithm)是一种用于求解单源最短路径问题的算法。它可以找到从一个顶点到其他所有顶点的最短路径。 以下是迪杰斯特拉算法的基本步骤: 1. 创建一个空的距离字典,用于存储每个顶点到起始顶点的距离。将起始顶点的距离设置为0,其他顶点的距离设置为无穷大。 2. 创建一个空的已访问集合,用于存储已经找到最短路径的顶点。 3. 重复以下步骤,直到所有顶点都被访问: a. 从未访问的顶点中选择距离起始顶点最近的顶点,并将其添加到已访问集合中。 b. 更新与该顶点相邻的顶点的距离。如果通过当前顶点到达相邻顶点的路径比之前计算的路径更短,则更新距离字典中的值。 4. 最终,距离字典中存储了从起始顶点到每个顶点的最短路径。 以下是一个使用Python实现迪杰斯特拉算法的示例代码: ```python import sys def dijkstra(graph, start): # 初始化距离字典 distances = {vertex: sys.maxsize for vertex in graph} distances[start] = 0 # 初始化已访问集合 visited = set() while len(visited) < len(graph): # 选择距离最小的顶点 min_distance = sys.maxsize min_vertex = None for vertex in graph: if vertex not in visited and distances[vertex] < min_distance: min_distance = distances[vertex] min_vertex = vertex # 将选中的顶点添加到已访问集合中 visited.add(min_vertex) # 更新与选中顶点相邻的顶点的距离 for neighbor, weight in graph[min_vertex].items(): new_distance = distances[min_vertex] + weight if new_distance < distances[neighbor]: distances[neighbor] = new_distance return distances # 示例图的邻接表表示 graph = { 'A': {'B': 5, 'C': 3}, 'B': {'A': 5, 'C': 1, 'D': 3}, 'C': {'A': 3, 'B': 1, 'D': 2, 'E': 6}, 'D': {'B': 3, 'C': 2, 'E': 4, 'F': 2}, 'E': {'C': 6, 'D': 4, 'F': 6}, 'F': {'D': 2, 'E': 6} } start_vertex = 'A' distances = dijkstra(graph, start_vertex) for vertex, distance in distances.items(): print(f"从顶点 {start_vertex} 到顶点 {vertex} 的最短距离为 {distance}") ``` 这段代码实现了迪杰斯特拉算法,通过邻接表表示图,并计算从起始顶点到其他顶点的最短距离。你可以根据自己的需求修改图的表示和起始顶点。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值