Dijkstra
简溪#
为什么要出现这个算法呢?
因为floyed就是逊啊
floyed的时间复杂度为O(N^3)因为他遍历了每个点到其他点的距离。
而有时只需要一个点到其他点的距离。此时,dijkstra闪亮登场。
该算法的核心是从边入手。
思考一下,如何才能保证一个点能够与另一个点距离确定?
思考片刻……
……
……
……
……
(不是在水😄
……
……
……
……
那就是与起始点相邻的点中,寻找一个距离最近的点。
为什么这个点就是确定的呢?应用floyed的思想:要更新一个点与另一个点的距离,要找一个中继点。详见floyed。如果这个点是最近的,那就无法再找到另一个点,使这个最近点与起始点更近。
- 1 号点的最近点是 4 号点,距离 3 。如果先到 5 号点,更新出来 1 号点到 4 号距离为 10
- 5 号点的最近点是 3 号点,距离为 2 ,从 1 号点更新 5 号点到 3 号点距离是 11
- 举个反例,如果把 7 作为 3 号 与 1 号点的距离,那么把 5 号点作为中继点,最短却是 6
最重要的一步已经解决,接下来是通过这个最短边延伸出的点,更新 1 号点与其他点的距离。因此,我们需要一个dis[N]的数组,以记录 1 号点到其他各个点的距离。
还需要一个flag[N]数组,记录dis[i]当中的点那个被选取过(这里的选取指的是在寻找与 1 号点最近点的点),比如 1 号点与 4 号点最近,flag[4]便更新为 1 ,而由 4 号点延伸出的点,不作flag的更新。
接下来的操作已经剧透,就是通过找到的点,遍历与它联通的点,如果 该点到中继点的距离+中继点到起始点的距离,小于dis[N]数组中该点的数组,就更新一下dis[i]。
特别注意
这里的dis[N]数组不一定是 1 号点到其他点的距离,视题目而定。这样的话,flag[N]的初始设定也要改为 flag[beg]=1。
并且题目找的是最短路,也要初始化。(最长路就别了)
代码#
#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
int n,m,dis[2510],f[2510][2510],s,t,k;
bool flag[2510];
int main(){
cin>>n>>m>>s>>t;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(i==j)
f[i][j]=0;
else
f[i][j]=inf;
}
}
for(int i=1;i<=m;i++){
int u,v,w;
cin>>u>>v>>w;
f[u][v]=min(f[u][v],w);
f[v][u]=f[u][v];
}
for(int i=1;i<=n;i++)
dis[i]=f[s][i];
flag[s]=1;
for(int i=1;i<=n-1;i++){
int maxn=inf;
for(int j=1;j<=n;j++){
if(dis[j]<maxn&&!flag[j]&&dis[j]!=0){
maxn=dis[j];
k=j;
}
}
flag[k]=1;
for(int j=1;j<=n;j++){
if(dis[j]>dis[k]+f[k][j]){
dis[j]=dis[k]+f[k][j];
}
}
}
cout<<dis[t];
return 0;
}
完结撒花🎉
2022年8月24日15:40:52
来放个链式前向星优化的
#include<iostream> #include<cstring> #include<climits> #include<vector> using namespace std; #define inf 2147483647 #define N 100010 #define ll long long vector<int> v[N]; int n, s, m, dis[N], k, head[N], tot; int pos; bool flag[N]; struct { int to, nxt, val; }e[N * 5]; void add(int u, int v, int w) { e[++ tot].to = v; e[tot].nxt = head[u]; e[tot].val = w; head[u] = tot; } int main(){ cin >> n >> m >> s; for(int i = 1; i <= m; ++ i){ int u, v, w; cin >> u >> v >> w; add(u, v, w); } for(int i = 1; i <= n; ++ i) dis[i] = inf; dis[s] = 0; flag[s] = 0; pos = s; while(flag[pos] == 0) { ll minn = inf; flag[pos] = 1; for(int i = head[pos]; i; i = e[i].nxt) { int t = e[i].to; if(!flag[t] && dis[t] > dis[pos] + e[i].val) dis[t] = dis[pos] + e[i].val; } for(int i = 1; i <= n; i ++) { if(!flag[i] && dis[i] < minn) { minn = dis[i]; pos = i; } } } for(int i = 1; i <= n; i ++) cout << dis[i] << " "; return 0; }
本文来自博客园,作者:huaziqi 转载请注明原文链接:https://www.cnblogs.com/huaziqi/p/16245445.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】