题目来源:算法笔记-亚历山大
第五天
题目:
输入格式:
第一行输入整数n, m, s;分别是图的顶点数,边数(单项边),起点编号;
接下来的m行,每行输入3个整数,v1, v2,w;代表顶点v1到v2有一条权重为w的边;
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
输出格式:
空格隔开的n个整数,代表n个顶点到起点的最短距离;
0 1 5 3 4 6
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 1010;
int G[N][N];
bool vis[N] = {0};
int d[N];
int n, m, s;//n个顶点,m条边,起点编号是s
void Dijkstra(int s) {
//对结果数组进行初始化
memset(d, 0x3f, sizeof(d));
d[s] = 0;
for(int i = 0; i < n; i++) { //一共要向集合S中加n个点(其实最多是n个点,因为可能有的点与起点不连通)
int MIN = INF, u = -1;
for(int i = 0; i < n; i++) {
if(d[i] < MIN && vis[i] == 0) {
u = i;
MIN = d[i];
}
}
if(u == -1) return ;
vis[u] = 1;
//不会再访问自己顶点,因为已经加入到集合S了
for(int i = 0; i < n; i++) {
if(vis[i] == 0) {
d[i] = min(d[i], d[u] + G[u][i]);
}
}
}
}
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 ", d[i]);
}
return 0;
}