Dijkstra | 适合蒟蒻(初学者)的算法解析(前置 F l o y d Floyd Floyd )
首先要弄懂啥是
D
i
j
k
s
t
r
a
Dijkstra
Dijkstra ?
D
i
j
k
s
t
r
a
Dijkstra
Dijkstra 是一个求最短路的算法废话
不同于
F
l
o
y
d
Floyd
Floyd
B
e
l
l
m
a
n
Bellman
Bellman
S
p
f
a
Spfa
Spfa (
S
p
f
a
Spfa
Spfa容易被卡
D
i
j
k
s
t
r
a
Dijkstra
Dijkstra 有
O
(
(
N
+
M
)
∗
l
o
g
N
)
O((N+M)*logN)
O((N+M)∗logN) 的优秀时间复杂度(不难写)
首先
D
i
j
k
s
t
r
a
Dijkstra
Dijkstra 是一个 贪心 *
F
l
o
y
d
Floyd
Floyd
先看看转移方程 (类似
d
p
dp
dp )
(
i
,
j
,
c
,
s
∈
[
1
,
n
]
i,j,c,s \in [1,n]
i,j,c,s∈[1,n] )
F
l
o
y
d
Floyd
Floyd :
d
i
s
[
i
]
[
j
]
=
d
i
s
[
i
]
[
c
]
+
d
i
s
[
c
]
[
j
]
dis[i][j]=dis[i][c]+dis[c][j]
dis[i][j]=dis[i][c]+dis[c][j]
D
i
j
k
s
t
r
a
Dijkstra
Dijkstra : 先令
d
i
s
[
i
]
dis[i]
dis[i] 表示 s 到 i
故
d
i
s
[
s
]
[
j
]
=
d
i
s
[
s
]
[
c
]
+
d
i
s
[
c
]
[
j
]
dis[s][j]=dis[s][c]+dis[c][j]
dis[s][j]=dis[s][c]+dis[c][j]
发现少了一个枚举i
但只能求s为起点的最短路了
不过…
正片开始
首先,搞定
D
i
j
k
s
t
r
a
Dijkstra
Dijkstra 的贪心部分
我们把pair(dis[i],编号)
存进priority_queue<pair<ll,int> >q;
这样就不用写operato了 q 会以
d
i
s
[
i
]
dis[i]
dis[i] 判断pair(dis[i],编号)
的位置
while{
然后用优先队列的性质,每次取最小的
d
i
s
[
j
]
,
p
o
p
(
)
dis[j],pop()
dis[j],pop()
接着把和j相连的点丢进q
用
d
i
s
[
s
]
[
j
]
=
d
i
s
[
s
]
[
c
]
+
d
i
s
[
c
]
[
j
]
dis[s][j]=dis[s][c]+dis[c][j]
dis[s][j]=dis[s][c]+dis[c][j]
如果队列为空 或 取到目标点t停止
}
最后输出就行
Code Time(题目参考:CF20C-Dijkstra?)
洛谷中文版
Codeforce英文版
本题需开long long
#include<bits/stdc++.h>
#define ll long long
#define N 100005
using namespace std;
vector<pair<int,ll> >node[N];
priority_queue<pair<ll,int> >q;
deque<ll>ans;
ll dis[N],vis[N],path[N];
int n,m;
signed main(){
ios::sync_with_stdio(false);//Line 11-20 read (1)
cin.tie(0);
cout.tie(0);
cin>>n>>m;
while(m--){
int u,v,w;
cin>>v>>u>>w;
node[v].push_back(make_pair(u,w));
node[u].push_back(make_pair(v,w));
}
q.push(make_pair(0,1));//Line 22-24 init
memset(dis,0x7f,sizeof dis);
dis[1]=0;
while(!q.empty()){
int u=q.top().second;
q.pop();
if(vis[u]==1){
continue;
}
else{//dis[s][j]=dis[s][c]+dis[c][j]
vis[u]==1;
for(int i=0;i<node[u].size();i++){ //(2)
if(dis[node[u][i].first]>dis[u]+node[u][i].second){
dis[node[u][i].first]=dis[u]+node[u][i].second;
path[node[u][i].first]=u;
q.push(make_pair(-dis[node[u][i].first],node[u
[i].first));
}
}
}
if(dis[n]==0x7f7f7f7f7f7f7f7f){
cout<<-1;
return 0;
}
int p=n;
while(path[p]){
ans.push_back(p);
p=path[p];
}
ans.push_back(1);
while(!ans.empty()){
cout<<ans.back()<<" ";
ans.pop_back();
}
return 0;
}
解释:
(1) 快读lower版,使cin,cout效率提升
(2)写不下了,分了行,以“;”为准