TOJ 565

TOJ 565

題敘

https://toj.tfcis.org/oj/pro/565/
給一張捷運的路線圖以及兩個整數 $A$ $B$ 和起點 $S$,從 $i$ 站到 $j$ 站所需要的花費為
$A經過路線數 + B經過路線權重總和$
求 $S$ 到各點所需的最小花費

想法

Dijkstra 模板題
如果點 $i$ 到點 $j$ 最短路徑為 $A$
則點 $i$ 到 $A$ 上的任一點的路徑也必定為最短路徑 (前提是邊權都是正的)
所以,我們可以每次都走距離最短的路,不斷更新起點到終點的距離,最終更新完必定會是最短距離

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
//By Koios1143
#include<bits/stdc++.h>
#define int long long
#define pii pair<int,int>
#define mp make_pair
using namespace std;
const int N = 1e5+10;
const int INF = 9223372036854775807;
int n,m,a,b,s;
vector<pii> E[N];
vector<int> dis(N,INF);
void dijkstra(){
priority_queue<pii> pq;
pq.emplace(dis[s]=0,s);
while(pq.size()){
int d,u;
tie(d,u)=pq.top();
d*=(-1);
pq.pop();
if(d!=dis[u]) continue;
for(auto e: E[u]){
int w,v;
tie(w,v)=e;
if(dis[v]<=dis[u]+a+b*w) continue;
dis[v]=dis[u]+a+b*w;
pq.emplace(-dis[v],v);
}
}
}

signed main(){
cin>>n>>m>>a>>b>>s;
for(int i=0,u,v,w ; i<m ; i++){
cin>>u>>v>>w;
E[u].emplace_back(w,v);
E[v].emplace_back(w,u);
}
dijkstra();
for(int i=1 ; i<=n ; i++){
cout<<dis[i]<<" ";
}
cout<<"\n";
return 0;
}

複雜度

使用 priority_queue 維護要加入的邊,複雜度為 $O(logN)$

總共有 $N$ 個點,總複雜度為 $O(NlogN)$