Dijkstra 算法

本文详细介绍了Dijkstra算法,包括其适用于正权边的特性、贪心思想以及朴素Dijkstra算法的步骤和时间复杂度分析。此外,还讨论了堆优化的Dijkstra算法,通过最小堆提高效率,以及提供了多种Dijkstra算法的实现方式。最后,给出了多个相关的练习题目供读者练习。
摘要由CSDN通过智能技术生成

Dijkstra 算法

只适用于正权边

思想是贪心的思想

朴素版Dijkstra 适合稠密图

朴素Dijkstra 思路

集合S为已经确定最短路径的点集。

初始化距离: 1 号结点的距离为零,其他结点的距离设为无穷大(看具体的题)。

循环 n 次,每一次将集合 S 之外距离最短 X 的点加入到 S 中去(这里的距离最短指的是距离 1 号点最近。点 X 的路径一定最短,基于贪心,严格证明待看)。然后用点 X 更新 X 邻接点的距离。

时间复杂度分析

寻找路径最短的点:O(n^2)O(n2)

加入集合S:O(n)O(n)

更新距离:O(m)O(m)

所以总的时间复杂度为 O(n^2)O(n2)

稠密图用邻接矩阵存图。

#include<iostream>#include<cstring>#include<cstdio>#include<algorithm>

using namespace std;

const int N = 510;

int g[N][N], dis[N];bool vis[N];   // 依据访问过与否将所有节点分成两个部分(集合)

int n, m;

void dijkstra(int s){

    memset(dis, 0x3f, sizeof(dis));

    memset(vis, 0, sizeof(vis));

    dis[s] = 0;

    for(int i = 1; i <= n; i++)

    {

        // 确定集合中距离初始节点最近的点 t

        int t = -1;

        for(int j = 1; j <= n; j++)

        {

            if(!vis[j] && (t == -1 || dis[j] < dis[t]))

                t = j;

        }

        vis[t] = true; // 加入 S 集合

        // 从 t 出发,更新相邻点的 dis

        for(int j = 1; j <= n; j++)

            dis[j] = min(dis[j], dis[t] + g[t][j]);

    }}

int main(){

    scanf("%d%d", &n, &m);

    memset(g, 0x3f, sizeof(g));

    while (m--)

    {

        int x, y, c;

        scanf("%d%d%d", &x

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值