Dijkstra算法具体解释
Dijkstra算法用于解决单源最短路径问题,即找出从一个源节点到其他所有节点的最短路径。该算法的前提是图中不能有负权边,因为它基于贪心策略。Dijkstra算法的基本思想是通过逐步确定到达每个节点的最短路径长度来求解问题。其主要步骤如下:
-
初始化:将源点到各个顶点的距离初始化为无穷大,源点的距离初始化为0。
-
选取源点:从未被标记为已确定最短路径的节点中选择一个距离最小的节点作为当前节点。
-
更新距离:对于当前节点的每个邻接节点,如果通过当前节点到达该邻接节点的路径比已知路径更短,则更新该邻接节点的最短路径长度。
-
标记节点:将当前节点标记为已确定最短路径。
-
重复步骤2至4,直到所有节点都被标记为已确定最短路径,或者找到了目标节点的最短路径。
核心:贪心策略
memset(d,0x3f,sizeof d);
d[x]=0;
for(int i=1;i<n;i++){
int u=0;
for(int j=1;j<=n;j++){
if(!st[j]&&d[j]<d[u]) u=j;
}
}
核心代码,目的是为了找在经历了i次松弛操作以后里x点最近的点,只要每次都是找最近的点,最后的距离就一定是最短的,当然dj处理不了负权边
洛谷P3371 【模板】单源最短路径(弱化版)
AC code(普通版n*n)
#include <bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
const int mod=2147483647;
int n,m,s;
int u,v,w;
vector<PII> vv[100010];
long long d[10010];
int st[10010];
void dijkstra(int x){
memset(d,0x3f,sizeof d);
d[x]=0;
for(int i=1;i<n;i++){
int u=0;
for(int j=1;j<=n;j++){
if(!st[j]&&d[j]<d[u]) u=j;
}
st[u]=1;
for(auto ed:vv[u]){
int a=ed.first,b=ed.second;
if(d[a]>d[u]+b) d[a]=d[u]+b;
}
}
}
int main()
{
cin>>n>>m>>s;
for(int i=0;i<m;i++){
cin>>u>>v>>w;
vv[u].push_back({v,w});
}
dijkstra(s);
for(int i=1;i<=n;i++){
if(d[i]<=1e9) cout<<d[i]<<" ";
else cout<<mod<<" ";
}
return 0;
}
P4779 【模板】单源最短路径(标准版)
堆优化版
#include <bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
const int mod=2147483647;
int n,m,s;
int u,v,w;
vector<PII> vv[200010];
long long d[100010];
int st[100010];
priority_queue<PII> q;
void dijkstra(int x){
memset(d,0x3f,sizeof d);
d[x]=0;q.push({0,x});
while(q.size()){
auto t=q.top();q.pop();
int u=t.second;
if(st[u]) continue;
st[u]=1;
for(auto ed:vv[u]){
int a=ed.first,b=ed.second;
if(d[a]>d[u]+b){
d[a]=d[u]+b;
q.push({-d[a],a});
}
}
}
}
int main()
{
cin>>n>>m>>s;
for(int i=0;i<m;i++){
cin>>u>>v>>w;
vv[u].push_back({v,w});
}
dijkstra(s);
for(int i=1;i<=n;i++){
if(d[i]<=1e9) cout<<d[i]<<" ";
else cout<<mod<<" ";
}
return 0;
}