给一个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<stdio.h>
#include<string.h>
#define N 3000
#define INF 0x3f3f3f3f
int e[N][N];
int dist[N]; ///起始点到各顶点i的距离
int visited[N];
int pre[N]; ///pre[i]=j,从j-->i
int n, m; ///顶点数,边数
int s, t; ///起点,终点
///初始化邻接矩阵
void init_e() {
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++)
if (i == j) e[i][j] = 0;
else e[i][j] = INF;
}
}
void Dijkstra() {
//memset(visited,0,sizeof(visited);
///初始化dist和pre,起始点到各顶点i的距离
for (int i = 1; i <= n; i++) {
dist[i] = e[s][i];
pre[i] = s; ///s-->i
}
visited[s] = 1;
for (int i = 2; i <= n; i++) {
int min = INF, u;
for (int i = 1; i <= n; i++) {
if (!visited[i] && dist[i] < min) {
min = dist[i];
u = i;
}
}
visited[u] = 1;
///遍历u的邻接顶点,更新dist
for (int i = 1; i <= n; i++) {
if (!visited[i] && dist[u] + e[u][i] < dist[i]) {
dist[i] = dist[u] + e[u][i];
pre[i] = u;
}
}
}
printf("%d\n", dist[t]);
}
///输出最短路径,递归
void search(int x){
if(x==s){
printf("%d",x );
return;
}
search(pre[x]);
printf("-->%d",x);
}
int main() {
scanf("%d%d%d%d", &n, &m, &s, &t);
init_e();
int a, b, w;
for (int i = 0; i < m; i++) {
scanf("%d%d%d", &a, &b, &w);
///邻接矩阵只能存两个顶点间的一条路,这儿处理题目中的注意事项
///只存两个顶点间最小的那条路
if (w < e[a][b]) {
e[a][b] = w;
e[b][a] = w; ///无向图
}
}
Dijkstra();
search(t); ///参数为终点
return 0;
}