Dijkstra:
使用该算法的前提是,已知起点求改点到其它顶点的最短路径,且两个顶点之间的路径必须大于等于0,如果要求任意两点的最短路径的话需要用Floyd算法。
算法思想:
1、两个集合,s,v分别表示已经得出起点到该点的最短路径的顶点,和其余顶点。
2、dist[]数组表示到起点的距离,a[][]数组储存两个顶点间的距离。
3、flag[]数组表示是否是s集合中的元素(为1表示是)。
4、然后在v集合中找离s集合中顶点最近的顶点,加入到s集合中,并且更新加入该顶点后v集合中的顶点到s集合中顶点的最短路径。
5、一直重复4直到所有顶点都在s集合中。
题目实例:
给一个n(1 ≤ n ≤ 2500) 个点 m(1 ≤ m ≤ 6200) 条边的无向图,求 s 到 t 的最短路。
输入格式:
第一行四个由空格隔开的整数 n、m、s、t。
之后的 m 行,每行三个正整数 si、ti、wi(1≤wi≤109),表示一条从si 到 ti 长度为 wi 的边。
输出格式:
一个整数,表示从s 到t 的最短路径长度。数据保证至少存在一条道路。
输入样例:
7 11 5 4
2 4 2
1 4 3
7 2 2
3 4 3
5 7 5
7 3 3
6 1 1
6 3 4
2 4 3
5 6 3
7 2 1
结尾无空行
输出样例:
7
结尾无空行
代码:
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
#include<set>
#include<vector>
using namespace std;
#define inf 0x3f3f3f3f
int a[2510][2510], flag[2510], dist[2510];
int n, m, s, t;
//算法
void Dijkstra() {
//初始化
memset(dist, inf, sizeof(dist));
memset(flag, 0, sizeof(flag));
//起始点到起始点的距离为0
dist[s] = 0;
//min1最小值,k为最小值的点
int min1, k;
//控制遍历次数
for (int i = 1; i <= n; i++)
{
k = -1;
min1 = inf;
//求出已经求出的最短路径点(s)到未求出的顶点的最小路径值和顶点(v)
for (int j = 1; j <= n; j++)
{
if (flag[j] == 0 && dist[j] < min1)
{
min1 = dist[j];
k = j;
}
}
flag[k] = 1;
//更新最短路径
for (int j = 1;j <= n;j++) {
if (flag[j]==0 && dist[j] > (dist[k] + a[k][j]) ) {
dist[j] = dist[k] + a[k][j];
}
}
}
}
int main() {
cin >> n >> m >> s >> t;
//初始化
for (int i = 1;i <= n;i++) {
for (int j = 1;j <= n;j++) {
a[i][j]=a[j][i]=inf;
}
}
//输入
while (m--) {
int x, y, w;
cin >> x >> y >> w;
a[x][y] = w;
a[y][x] = w;
}
Dijkstra();
cout << dist[t];
return 0;
}