迪杰斯特拉(dijkstra)最短路算法详解

这里更多算法(更好的阅读体验)

dijkstra最短路算法

算法过程(不包含初始化)

  1. 从起点s开始,更新相连节点距离(其实就是如果有直接距离就更新直接距离)
  2. 将起点s标记为 “已访问过”
  3. 在“未访问的节点”上寻找离起点最近的节点pos(相当于 1. 的起点)
  4. 将节点pos标记为“已访问过”
  5. 寻找 与节点pos相连(有路径)的、未被标记为“已访问过”的 节点j,并更新节点j到初始节点最近距离
  6. 重复 3. 4. 步骤
  7. 直到所有的节点都被标记为“已访问过”,跳出循环
  8. 输出距离

代码实现(链式前向星 + dijkstra)

链式前向星此代码不详解

#include <bits/stdc++.h>

using namespace std;
//我不编译所以变量名直接用简洁明了的意思了

const int N = 节点数 + 5, M = 边数 + 5, ma = INT_MAX;
//加5是为了防止数据溢出导致RE
struct Edge{
    int to, cost, next;
};

Edge e[M * 2];
int head[N], ans[N], cnt = 1;
//  头节点集合 最短距离
bool flag[N];//是否被标记过

void add(int from, int to, int cost){
    e[cnt].to = to;
    e[cnt].cost = cost;
    e[cnt].next = head[from];
    head[from] = cnt;
    cnt ++;
}

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    //大数据输入输出优化
    
    freopen("xxx.in", "r", stdin);
    freopen("xxx.out", "w", stdout);
    //读入文件类型数据(比赛用)

    int n, m, s;//n 节点数 m 边数 s 初始节点
    cin >> n >> m;
    for(int i = 1; i <= m; ++ i){
        int x, y, z;
        cin >> x >> y >> z;
        add(x, y, z);
        add(y, x, z);
        //存双向边
    }

    //以下为初始化过程
    for(int i = 1; i <= n; ++ i)
        ans[i] = ma;
    //将每个节点到初始节点的距离设为无穷大,方便更新答案
    for(int i = head[s]; i; i = e[i].next)
        ans[e[i].to] = e[i].cost;
    //步骤1
    ans[s] = 0;//初始节点到初始节点的距离为0
    flag[s] = true;
    //步骤2
    while(1){
    //步骤 6
        int tmp = ma, pos = s;
        for(int i = 1; i <= n; ++ i)
            if(!flag[i] && tmp > ans[i]){
                tmp = ans[i];
                pos = i;
            }
    //步骤3
        if(pos == s) break;
    //步骤7
        flag[pos] = true;
    //步骤4
        for(int i = head[pos]; i; i = e[i].next)
            if(![e[i].to] && ans[e[i].to] > ans[pos] + e[i].cost)
                ans[e[i].to] = ans[pos] + e[i].cost;
    //步骤5

    }

    for(int i = 1; i <= n; ++ i)
        cout<< ans[i] << " ";
    //步骤8

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值