【PTA数据结构 | C语言版】求单源最短路的Dijkstra算法

本专栏持续输出数据结构题目集,欢迎订阅。

文章目录

题目

请编写程序,实现在带权的有向图中求单源最短路的 Dijkstra 算法。

注意:当多个待收录顶点路径等长时,按编号升序进行收录。

输入格式:

输入首先在第一行给出两个正整数,依次为当前要创建的图的顶点数 n(≤100)和边数 m。

随后 m 行,每行给出一条有向边的起点编号、终点编号、权重。顶点编号从 0 开始,权重(≤100)为整数。同行数字均以一个空格分隔。

输出格式:

参考样例。按顶点编号的升序,每行输出一个顶点的信息,格式为:

复制代码
v[i]: dist=x, path=y

其中 i 为顶点编号;x 为顶点 0 到顶点 i 的最短距离;y 为对应的最短路径上,i 的前驱顶点编号。因为起点 0 没有前驱顶点,所以对应的 y 记为 -1。

输入样例:

6 9

0 1 1

0 2 12

1 2 9

1 3 3

2 4 5

3 2 4

3 4 13

3 5 15

4 5 4

输出样例:

v[0]: dist=0, path=-1

v[1]: dist=1, path=0

v[2]: dist=8, path=3

v[3]: dist=4, path=1

v[4]: dist=13, path=2

v[5]: dist=17, path=4

代码

cpp 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>

#define MAX_VERTEX 100    // 最大顶点数
#define INF INT_MAX       // 表示无穷大

int main() {
    int n, m;
    scanf("%d %d", &n, &m);
    
    // 初始化邻接矩阵,全部设为无穷大
    int graph[MAX_VERTEX][MAX_VERTEX];
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            graph[i][j] = INF;
        }
    }
    
    // 读取边信息并填充邻接矩阵
    for (int i = 0; i < m; i++) {
        int u, v, w;
        scanf("%d %d %d", &u, &v, &w);
        graph[u][v] = w;  // 有向边,只设置一个方向
    }
    
    // Dijkstra算法所需数组
    int dist[MAX_VERTEX];   // 存储从源点到各顶点的最短距离
    int path[MAX_VERTEX];   // 存储最短路径上各顶点的前驱
    int collected[MAX_VERTEX];  // 标记顶点是否已收录
    
    // 初始化
    for (int i = 0; i < n; i++) {
        dist[i] = graph[0][i];  // 初始距离为源点(0)到i的直接距离
        if (dist[i] < INF) {
            path[i] = 0;        // 有直接路径,前驱为源点
        } else {
            path[i] = -1;       // 无直接路径,前驱为-1
        }
        collected[i] = 0;       // 所有顶点初始均未收录
    }
    
    // 源点自身初始化
    dist[0] = 0;
    path[0] = -1;
    collected[0] = 1;
    
    // 主循环:每次收录一个顶点,共收录n-1个(源点已收录)
    for (int i = 0; i < n - 1; i++) {
        // 步骤1:找出未收录顶点中dist最小的顶点v
        int min_dist = INF;
        int v = -1;
        
        for (int j = 0; j < n; j++) {
            if (!collected[j]) {
                // 当距离相等时,选择编号较小的顶点(天然满足,因按编号遍历)
                if (dist[j] < min_dist) {
                    min_dist = dist[j];
                    v = j;
                }
            }
        }
        
        // 若没有可收录的顶点(图不连通),提前退出
        if (v == -1) break;
        
        // 步骤2:收录顶点v
        collected[v] = 1;
        
        // 步骤3:更新所有未收录的邻接顶点的dist和path
        for (int w = 0; w < n; w++) {
            // 若w未收录且v到w有边
            if (!collected[w] && graph[v][w] < INF) {
                // 若经过v到w的路径更短
                if (dist[v] + graph[v][w] < dist[w]) {
                    dist[w] = dist[v] + graph[v][w];
                    path[w] = v;
                }
            }
        }
    }
    
    // 按顶点编号升序输出结果
    for (int i = 0; i < n; i++) {
        printf("v[%d]: dist=%d, path=%d\n", i, dist[i], path[i]);
    }
    
    return 0;
}    
相关推荐
jstart千语1 小时前
【力扣】第42题:接雨水
算法·leetcode·职场和发展
墨染点香1 小时前
LeetCode 刷题【10. 正则表达式匹配】
算法·leetcode·职场和发展
cookqq1 小时前
mongodb源代码分析createCollection命令由create.idl变成create_gen.cpp过程
数据库·算法·mongodb·nosql
clock的时钟1 小时前
数据结构-线性表顺序表示
数据结构·算法
WanderInk2 小时前
深入解析:Java Arrays.sort(intervals, Comparator.comparingInt(a -> a[0])); 一行代码的背后功力
java·后端·算法
এ᭄画画的北北2 小时前
力扣-70.爬楼梯
算法·leetcode
nako_sayuri2 小时前
二分查找:区间内查询数字的频率
数据结构·算法
404未精通的狗2 小时前
(数据结构)线性表(中):SLIst单链表
c语言·数据结构·链表
艾莉丝努力练剑2 小时前
【LeetCode&数据结构】栈的应用——有效的括号问题详解
c语言·开发语言·数据结构·学习·链表
The Chosen One9852 小时前
C++的“链”珠妙笔:list的编程艺术
开发语言·数据结构·c++·list