日期:2023.10.15
第5天
输入:
6 8 0
0 1 1
0 3 4
0 4 4
1 3 2
2 5 1
3 2 2
3 4 3
4 5 3
期望输出的最短距离(没有涉及到最短路径):
0 1 5 3 4 6
/*
求路径需要增加一个pre[]数组
*/
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 1010;
int d[N];
bool vis[N] = {0};
int pre[N] = {-1};
int G[N][N];
int n, m, s;//顶点数、边数、起点
void Dijkstra(int s) {
memset(d, 0x3f, sizeof(d));
d[s] = 0;
//每个节点的前驱为自身;
for(int i = 0; i < n; i++) {
pre[i] = i;
}
for(int i = 0; i < n; i++) { //一共让集合S加入n个点
//第一层循环找非集合S中距离起点最近的
int MIN = INF, u = -1;
for(int j = 0; j < n; j++) {
if(vis[j] == 0 && d[j] < MIN) {
MIN = d[j];
u = j;
}
}
if(u ==-1) return ;
vis[u] = 1;
//更新非S集合中,和点U相连的点,到起点距离
for(int j = 0; j < n; j++) {
if(vis[j] == 0 && G[u][j] != INF) {
d[j] = min(d[j], d[u] + G[u][j]);
//它的前一个结点更新一下;
pre[j] = u;
}
}
}
}
//使用dfs()可以正着输出路径:要求:给出一个顶点,输入起点到这个点的路径,我们只知道它的前一个结点,先深度遍历到根节点
void dfs(int s, int v) { //s是起点, v是目标点
//终止条件:
if(v == s) {
printf("%d ", s);
return ;
}
dfs(s, pre[v]);
printf("%d ", v);
}
int main(void) {
scanf("%d%d%d", &n, &m, &s);
memset(G, 0x3f, sizeof(G));
for(int i = 0; i < m; i++) {
int id1, id2, w;
scanf("%d%d%d", &id1, &id2, &w);
G[id1][id2] = w;
}
Dijkstra(s);
for(int i = 0; i < n; i++) {
printf("最短距离%d\n ", d[i]);
//如果用一个循环的话,只能倒着输出
printf("路径为:");
for(int j = i; j >= 0; j = pre[j]) {
printf("%d-->", j);
if(j == 0) break;
}
printf("\n");
}
for(int i = 0; i < n; i++) {
dfs(s, i);
printf("\n");
}
return 0;
}
其他:这两天给ubuntu装n卡驱动,心态优点小崩。