【最短路算法】Dijkstra知识点&代码

代码:

复制代码
#include<iostream>
#include<vector>
#include<cstdio>
#include<queue>
#include<map>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<set>
#include<cstring>
using namespace std;
typedef long long ll;
const ll INF=2147483647;
const int MM=500002;
const int NM=10002;
int n,m,s;//点,边,起始
int dis[NM];//最小距离
bool book[NM];//记录有没有作为顶点搜索过
//链式向前星
struct NODE{
    int to;
    int nxt;
    int c;
}node[MM];//链式向前星
int head[NM],lcnt=1;
void add(int a,int b,int c){
    node[lcnt].to=b;
    node[lcnt].c=c;
    node[lcnt].nxt=head[a];
    head[a]=lcnt++;
}
int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cin>>n>>m>>s;
    for(int i=1;i<=n;i++){
        dis[i]=INF;
    }
    for(int i=0;i<m;i++){
        int a,b,c;
        cin>>a>>b>>c;
        //if(a==b)
        //    continue;

        add(a,b,c);
        //add(b,a,c);
    }
    for(int i=head[s];i;i=node[i].nxt){             //从起始点开始枚举
        int idx=node[i].to;                           
        dis[idx]=min(node[i].c,dis[idx]);            //更新最短路
        
    }
    dis[s]=0;                   //自身距离为0 
    book[s]=1;                //标记搜索过
    for(int kkk=1;kkk<n;kkk++){          //枚举每个点(用编号)
        int minn=INF,u=0;
        for(int i=1;i<=n;i++){
            if(!book[i]&&dis[i]<minn){        
                u=i;                                 //枚举每个已经被标记了但是没有被搜索过的点
                minn=dis[i];                      //找距离最小的
            }
        }
    
        
        /*for(int i=1;i<=n;i++){
            if(mp[u][i]<INF){
                dis[i]=min(dis[i],dis[u]+mp[u][i]);
            }
        }*/
        
        for(int i=head[u];i;i=node[i].nxt){
            int idx=node[i].to;                                //正在搜索的点开始,枚举每一条边
            
            dis[idx]=min(dis[idx],dis[u]+node[i].c);      //更新最短距离,设f[i][j]为i到j的最大距离,d[i]为起始点到i的距离
                                                                    //得到    d[j]=min(d[j],d[i]+f[i][j])
        }
        
        book[u]=1;                                              //标记这个点搜索过了
        
    }
    for(int i=1;i<=n;i++){
        cout<<dis[i]<<" ";
    }
    return 0;
}
查看神奇代码
复制代码

 

1.储存方式:

链式向前星>> https://www.cnblogs.com/dudujerry/p/9915713.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int n,m,s;//点,边,起始
int dis[NM];//最小距离
bool book[NM];//记录有没有作为顶点搜索过
//链式向前星
struct NODE{
    int to;
    int nxt;
    int c;
}node[MM];//链式向前星
int head[NM],lcnt=1;
void add(int a,int b,int c){
    node[lcnt].to=b;
    node[lcnt].c=c;
    node[lcnt].nxt=head[a];
    head[a]=lcnt++;
}

  

2.更新所有与根节点连接的最短路

1
2
3
4
5
6
7
for(int i=head[s];i;i=node[i].nxt){             //枚举所有与起点连接的边
    int idx=node[i].to;                          
     dis[idx]=min(node[i].c,dis[idx]);            //更新最短路
         
}
dis[s]=0;                   //自身距离为0
book[s]=1;                //标记搜索过

使用book记录是否作为过用来更新的点, 则搜完之后 book[s]=1

 

3.接下来枚举除源点外所有点来作为用来更新最短路的点

依 ”从上次求出最短路的点中选出最短路最小的点“ 的顺序遍历除源点以外的n-1个点

1
2
3
4
5
6
7
8
for(int kkk=1;kkk<n;kkk++){          //枚举n-1次,因为原点已经被用来更新过了
        int minn=INF,u=0;
        for(int i=1;i<=n;i++){                 
            if(!book[i]&&dis[i]<minn){        //枚举每个已经被标记了但是没有被搜索过的点
                u=i;                                
                minn=dis[i];                      //找距离最小的
            }
        }<br>              . . .

 

 

4.从选出的点开始更新所有与它连接的边

设已知 源点到i点的距离dis[i] 和 点i到点j的距离f[i][j]    (未知当前dis [ j ]是否正确)

可以得到  dis [ j ] = min ( dis [ j ] , dis [ i ] + f [ i ] [ j ] )

根据上面的方程可以遍历所有与选出的点,算出最短路

 

1
2
3
4
5
6
7
8
9
10
     . . .<br>          for(int i=head[u];i;i=node[i].nxt){
        int idx=node[i].to;                                //正在搜索的点开始,枚举每一条边
         
        dis[idx]=min(dis[idx],dis[u]+node[i].c);      //更新最短距离,设f[i][j]为i到j的最大距离,d[i]为起始点到i的距离
                                                                //得到    d[j]=min(d[j],d[i]+f[i][j])
    }
     
    book[u]=1;                                              //标记这个点搜索过了
     
}

  

 

5.输出

dis [ i ]就是源点到i点的距离

1
2
3
for(int i=1;i<=n;i++){
        cout<<dis[i]<<" ";
    }

  

posted @   dudujerry  阅读(179)  评论(0编辑  收藏  举报
编辑推荐:
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示