一、最短路径
- 最短路径问题是图论研究中的一个经典算法问题, 旨在寻找图(由结点和路径组成的)中两结点之间的最短路径。
- 算法具体的形式包括:
- 确定起点的最短路径问题 - 即已知起始结点,求最短路径的问题。
- 确定终点的最短路径问题 - 与确定起点的问题相反,该问题是已知终结结点,求最短路径的问题。在无向图中该问题与确定起点的问题完全等同,在有向图中该问题等同于把所有路径方向反转的确定起点的问题。
- 确定起点终点的最短路径问题 - 即已知起点和终点,求两结点之间的最短路径。
- 全局最短路径问题 - 求图中所有的最短路径。
二、Dijkstra算法(迪杰斯特拉算法)
算法步骤
初始化:
- 将源点v0加到S中,即S[v0] = true;
- 将v0到各个终点的最短路径长度初始化为权值,即D[i] = G.arcs[v0][vi] (vi ∈ V-S);
- 如果v0和顶点vi之间有弧,则将vi的前驱置为v0,即Path[i] = v0,否则Path[i] = -1;
循环n-1次,执行以下操作:
- 选择下一条最短路径的终点vk,使得:D[k] = Min{D[i] | vi ∈ V-S};
- 将vk加到S中,即S[vk] = true;
- 根据条件更新从 v0 出发到集合 V-S 上任一顶点的最短路径的长度,若条件 D[k] + G.arcs[k][i] < D[i] 成立,则更新 D[i] = D[k]+G.arcs[k][i], 同时更改 vi 的前驱为 vk; Path[i] = k;
三、举个栗子(1077 : Dirjkstra)
Description
给定n个点,m条有向边, 求每个点到1号点的最短距离
Input
- 第一行两个数为n,m,n表示顶点个数,m表示边的条数。 (1 ≤ n, m ≤ 100 )
- 接下来m行,每一行有三个数t1、t2 和t3,表示顶点 t1 到顶点 t2 的路程是 t3。请注意这些 t1 -> t2 是单向的。
Output
输出N个数,分别为每个点到1号点的距离。
Sample Input
6 9
1 2 1
1 3 12
2 3 9
2 4 3
3 5 5
4 3 4
4 5 13
4 6 15
5 6 4
Sample Output
0 1 8 4 13 17
code
详见注释
#include <iostream>
#define Max 503
#define INF 0xcffffff
using namespace std;
typedef struct AMGraph { //定义图
int vex, arc;
int arcs[Max][Max]; //邻接矩阵
};
int dis[Max], path[Max]; //dis保存最短路径总权值、path通过保存路径的前驱结点来保存路径
bool book[Max]; //已找到最短路集合
void Dijkstra(AMGraph &G) //迪杰斯特拉算法
{
for (int i = 1; i <= G.vex; i++)
{
dis[i] = G.arcs[1][i]; //初始化dis数组
path[i] = dis[i] < INF ? 1 : -1; //初始化路径数组
}
book[1] = true;
dis[1] = 0; //起点初始化
for (int i = 2; i <= G.vex; i++) //遍历G.vex-1次
{
int mins = INF, u = 1;
for (int j = 1; j <= G.vex; j++) //找到当前没加入集合的最短路的后驱点
{
if (!book[j] && mins > dis[j]) {
mins = dis[j];
u = j;
}
}
book[u] = true; //将该点加入集合
for (int j = 1; j <= G.vex; j++) //遍历所有其他点对其最短路进行更新(松弛操作)
{
if (!book[j] && dis[j] > dis[u] + G.arcs[u][j]) {
dis[j] = dis[u] + G.arcs[u][j]; //更新最短路径值
path[j] = u; //修改j的前驱为u
}
}
}
}
void find(int x) //递归输出最短路径
{
if (path[x] == 1) {
cout << 1;
}
else {
find(path[x]);
}
cout << " -> " << x;
return;
}
void putin(AMGraph &G) //输入图
{
cin >> G.vex >> G.arc;
for (int i = 1; i <= G.vex; i++) //初始化邻接矩阵
for (int j = 1; j <= G.vex; j++)
G.arcs[i][j] = INF;
for (int i = 1; i <= G.arc; i++)
{
int u, v, w;
cin >> u >> v >> w;
G.arcs[u][v] = w;
}
}
void putout(AMGraph &G) //输出
{
//cout << "起点 v1 到各点的最短路程为: \n";
for (int i = 1; i < G.vex; i++)
{
cout << dis[i] << " ";
}
cout << dis[G.vex] << endl;
/*for (int i = 2; i <= G.vex; i++)
{
cout << "起点 v1 到 v" << i << " 的路径为: ";
find(i);
cout << endl;
}*/
}
int main()
{
AMGraph G;
putin(G);
Dijkstra(G);
putout(G);
return 0;
}
运行截图
去注释打印路径结果
蒟蒻一只,欢迎指正