最短路算法

图论:最短路径算法

最短路:

最短路主要分为,单源最短路 和 多源汇最短路。

在单源最短路中要区分是否含有负权边,如果图中不含负权边使用主要算法有 dijkstra 算法,而含负权边则使用 bellman-ford 算法 或 spfa 算法。

在多源汇最短路中主要有 floyd 算法。

在这里插入图片描述

单源最短路:不含负权边、

朴素 dijkstra 算法

算法流程:假设存在 n 个点,m 条边,求 s 点到任意一点的最短距离

  1. 定义一个数组 dist,dist[i] 表示从 s 点到点 i 的距离。
  2. 初始化 dist,将 s 点初始化为 0,其余点初始化正无穷 (只要比图中任意一条边的权值都大,这个数不会影响到求解过程)
  3. 循环确定每个点到 s 的距离,因为 s 到 s 为 0,所以还剩 n - 1 个点需要确定,就循环 n - 1次。在每次循环中,
    • 找到距离 s 最近的一个点,且这个点没有确定
    • 用这个点去更新,其他点判断是否能使其它点到 s 的距离变短,如果能就将其更新,否则保持不变
    • 一次循环结束时将这个点打上记号,表示当前点以确定

代码:

const int N = 1010;
int g[N][N]; // 使用邻接矩阵来存图
bool st[N]; // 标记:i 点是否已确定
int n;

void dijkstra(int s){
    int dist[N];
    // 初始化
    memset(dist, 0x3f, sizeof dist);
    dist[s] = 0;
    
    for(int i = 0; i < n - 1; i ++) {
        int t = -1;
        for(int j = 1; j <= n; j++) {
            if(!st[j] && (t == -1 || st[t] > st[j])) // 找到距离 s 最近的一个点,且这个点没有确定
                t = j;
        }
        
        for(int j = 1; j <= n; j++) {
            dist[j] = min(dist[j], dist[t] + g[t][j]); // 用这个点去更新,其他点判断是否能使其它点到 s 的距离变短,如果能就将其更新,否则保持不变
        }
        st[t] = true; // 一次循环结束时将这个点打上记号,表示当前点以确定
    }
}
题目:P3371 【模板】单源最短路径(弱化版)
题目背景

本题测试数据为随机数据,在考试中可能会出现构造数据让SPFA不通过,如有需要请移步 P4779

题目描述

如题,给出一个有向图,请输出从某一点出发到所有点的最短路径长度。

输入格式

第一行包含三个整数 n,m,sn,m,s,分别表示点的个数、有向边的个数、出发点的编号。

接下来 mm 行每行包含三个整数 u,v,wu,v,w,表示一条 u \to vuv 的,长度为 ww 的边。

输出格式

输出一行 nn 个整数,第 ii 个表示 ss 到第 ii 个点的最短路径,若不能到达则输出 2^{31}-1231−1。

输入输出样例

输入 #1复制

4 6 1
1 2 2
2 3 2
2 4 1
1 3 5
3 4 3
1 4 4

输出 #1复制

0 2 4 3
说明/提示

【数据范围】
对于 20%20% 的数据:1\le n \le 51≤n≤5,1\le m \le 151≤m≤15;
对于 40%40% 的数据:1\le n \le 1001≤n≤100,1\le m \le 10^41≤

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值