【算法】堆优化版Dijkstra算法(最短路问题)

描述了如何使用Dijkstra算法解决有向图中从1号点到n号点的最短路径问题,利用小根堆优化搜索过程。
摘要由CSDN通过智能技术生成

题目

给定一个 n 个点 m 条边的有向图,图中可能存在重边和自环,所有边权均为非负值。

请你求出 11 号点到 n 号点的最短距离,如果无法从 1 号点走到 n 号点,则输出 −1。

输入格式

第一行包含整数 n 和 m。

接下来 m 行每行包含三个整数 x,y,z,表示存在一条从点 x 到点 y 的有向边,边长为 z。

输出格式

输出一个整数,表示 1 号点到 n 号点的最短距离。

如果路径不存在,则输出 −1。

数据范围

1≤n,m≤150000
图中涉及边长均不小于 0,且不超过 10000。
数据保证:如果最短路存在,则最短路的长度不超过 1e9。

思路

 使用小根堆来优化查询当前最短距离的点,使用当前没有遍历过的最小距离的点对其他的进行更新。

代码

#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;

typedef pair<int,int> PII;
const int N = 200010;
int n,m;//n个点,m条边
int h[N],e[N],ne[N],w[N],idx;// 邻接表四件套,w存放边的长度
int dist[N]; // 确定最小距离的点i距离点1的距离
bool st[N];// 表示这个点是否被遍历过

void add(int a,int b,int c)
{
    e[idx] = b,w[idx] = c,ne[idx] = h[a],h[a] = idx ++;// 建立邻接表,并将边长存放在w中
}

int dijkstra()
{
    memset(dist,0x3f,sizeof dist);
    dist[1] = 0;// 点1已经确定,并且距离为0

    priority_queue<PII,vector<PII>,greater<PII>> heap;// 小根堆,
    heap.push({0,1});// 将点的距离存到first中,将点的编号存到second中。

    while(heap.size())
    {
        auto t = heap.top();//取出这个小根堆中距离最小的点
        heap.pop();// 将取出的点从小根堆中删除

        int ver = t.second,distance = t.first;// 使用ver存点的编号,使用distance存放这个点到点1的最小距离
        if(st[ver]) continue;// 如果这个点被遍历过,则直接进行下次循环
        st[ver] = true;// 如果没有遍历过,就进行加下来的操作,并对这个点进行标记

        for(int i = h[ver]; i != -1; i = ne[i])// 遍历这个点的邻接表
        {
            int j = e[i];// 跟这个点临接的某一个点的编号使用j存储。
            if(dist[j] > distance + w[i])// 如果邻接点当前的距离大于,则更新这个点
            {
                dist[j] = distance + w[i];
                heap.push({dist[j],j});
            }
        }
    }
    if(dist[n] == 0x3f3f3f3f) return -1;
    return dist[n];
}

int main()
{
    cin >> n >> m;
    memset(h,-1,sizeof h);
    while(m --)
    {
        int a,b,c;
        scanf("%d%d%d",&a,&b,&c);
        add(a,b,c);
    }
    int ans = dijkstra();
    cout << ans << endl;
    return 0;
}

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一只大黄猫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值