最短路1(Dijkstra算法)| | [模板]单源最短路 题解

本文介绍了Dijkstra算法,用于寻找无负权边图中的最短路径。该算法基于贪心策略,每次选取未确定路径中到起点距离最小的顶点,通过更新其他顶点的距离来逐步扩展最短路径。文中还给出了C++实现代码示例和一个标准输入输出的例子。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最短路——Dijkstra算法

(〇)框架

本文章着重讲价其中的Dijkstra算法 

23072608185689.png

(一)Dijkstra算法

使用前提:没有负权的边

Dijkstra求最短路径思路

基于贪心思想,给定图G,边集合E,顶点集合V。每次求出从起点Vs到一个顶点Vi的最短路径,然后以Vi为中转点,用Vs到Vi的最短路径 和 其他尚未求出最短路径的点的路径长度 进行必要的修改,使之成为当前最优的最短路径。

进行n-1此后结束,因此我们也可以用它来判断是否存在负权环。

总结一下: 每次选择【未确定】最短路径中,到原点【路径长度最小的点】

实现?

基于上述所说的几点,我们来思考一下如何实现:
1.用vis[]数组储存未确定最短路径的点

2.用dis[]数组储存当前点距离原点的最短距离

Dijkstra求最短路流程:

1.定义dis[](初值赋无穷大),vis[]数组,集合S(储存已找到的从Vs出发的最短路径的集合)

2.选择(离当前点)距离最短的顶点Vp,加入集合S,vis[Vp]=1;

3.更新vis[]数组中各个顶点到起点s的距离。之所以更新vis[]数组中顶点的距离,是由于上一步中确定了k是求出最短路径的顶点,从而可以利用k来更新其它顶点的距离;

4.重复2、3步骤知道遍历完所有顶点

图解

23072608112469.png

23072608235316.png

23072608309618.png

23072608181193.png

例题:[模板]单源最短路

题目描述

给定一个 n 个点,m 条有向边的带非负权图,请你计算从 s 出发,到每个点的距离。

数据保证你能从 s 出发到任意点。

输入格式

第一行为三个正整数 n,m,s。第二行起 m 行,每行三个非负整数 ui,vi,wi,表示从 ui 到 vi 有一条权值为 wi 的有向边。

输出格式

输出一行 n 个空格分隔的非负整数,表示 s 到每个点的距离。

输入
4 6 1
1 2 2
2 3 2
2 4 1
1 3 5
3 4 3
1 4 4
输出
0 2 4 3

代码及解释

#include<bits/stdc++.h>
#define pii pair<int,int>
using namespace std;
const int maxn=500005;
int n,m,s,u,v,w;

struct node{
    int to,len;
};

vector<node> f[maxn];
long long dis[maxn];
int vis[maxn];

void dijkstra(int t)
{
    priority_queue<pii,vector<pii>,greater<pii> > q;
    dis[t]=0;//起点距离为零
    q.push(pii(0,t));//起点输入
    while(!q.empty()){//只要队列不为空,就一直循环下去
        pii x=q.top();//将队列顶部的元素顶点存下来 
        q.pop();//弹出队顶元素
        int tt=x.second;
        if(vis[tt]) continue;//判断是否访问过
        vis[tt]=1;//标记为访问过
        for(int i=0;i<f[tt].size();i++){
            node a=f[tt][i];
            if(dis[a.to]>dis[tt]+a.len){
                dis[a.to]=dis[tt]+a.len;
                q.push(pii(dis[a.to],a.to));
            }
        }
    }
}

int main()
{
    cin>>n>>m>>s;
    for(int i=0;i<m;i++){
        cin>>u>>v>>w;
        f[u].push_back({v,w});
    }
    for(int i=1;i<=n;i++){
        dis[i]=114514191;
    }//1145141919810 
    memset(vis,0,sizeof(vis));
    dijkstra(s);
    for(int i=1;i<=n;i++){
        if(dis[i]!=114514191)
        cout<<dis[i]<<endl;
    }
    return 0;
}

完结撒花

(后续将更新其他最短路算法,敬请期待)

(图片来源)wmy0217_ icon-default.png?t=N7T8https://blog.youkuaiyun.com/wmy0217_heroacool icon-default.png?t=N7T8https://heroacool.blog.youkuaiyun.com/

 我只是想要一个小小的赞👍

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值