朴素dijkstra解决单源最短路问题

一. 单源最短路问题---Dijkstra(基于贪心)

A.边权为正

储存图的数据结构:邻接表(稀疏图)或邻接矩阵(稠密图)

算法需要的基本数据结构:

1.Set 集合 (实际用bool数组代替)用于存放已求得最短路径的顶点

2.dist[] : 存放对应顶点到源点的最短路径,初始态仅源点邻居存在有值,其余为∞

3.arcs[ i] [j]: i--j 的边权 ,无边则为∞ (这个数组无需修改)

步骤 :

1.初始化S集合为空,dist赋值初始态

2.从不属于Set集合的顶点中选出最近的一个顶点(dist[]值最小)加入Set(记为j号顶点)

3.更新源点到不属于Set集合的顶点集的所有dist[] ,将现有的dist[k]值跟 dist[j]+arcs[j] [k] 比较(注:j是刚确认的最小dist顶点,k为任意不属于Set的顶点)

基本原理:基于贪心,选出每一段的最短距离,最终的距离也是最短。

不能有负权边的原因:手动模拟会发现不满足贪心策略,根据朴素dijstra 每个顶点只会被更新一次最短路径,但是可能出现已经更完最短路的结点连接负权,而后却无法修改的情况。

题目:

image-20220412225126209

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=505;
int dist[N];
int arcs[N][N];
bool st[N]; //set集合的具象表示
int n,m;

int dijkstra(){
    memset(dist,0x3f,sizeof dist);
    dist[1]=0; //1为源点
    
    for(int i=0;i<n-1;i++){ //每次找一个t放入集合
        int t=-1;
        for(int j=1;j<=n;j++){
            if(!st[j] && (t==-1 || dist[t] > dist[j])){ //找出不在Set中的最小的dist,记为t
                t=j;
            }
        }
        st[t]=true;
        for(int j=1;j<=n;j++){
            dist[j]=min(dist[j],dist[t]+arcs[t][j]); //更新所有不再Set中的顶点值,基于上一次的dist[j](min)
        }
    }

    if(dist[n]==0x3f3f3f3f) return -1 ;//1到n的路径不存在
    return dist[n];
}


int main()
{
    memset(arcs,0x3f,sizeof arcs);
    cin>>n>>m;
    while (m -- ){
        int x,y,z;
        cin>>x>>y>>z;
        arcs[x][y]=min(z,arcs[x][y]);
    }
    cout<<dijkstra();
        
    return 0;
}
posted @ 2022-04-29 22:59  秋月桐  阅读(21)  评论(0编辑  收藏  举报