我們用以下程式碼為例分析複雜度
#include<bits/stdc++.h>
#include<climits>
#define fir first
#define se second
using namespace std;
typedef long long ll;
typedef pair<ll,int> PII;
inline int read() {
int x=0,f=1; char c=getchar();
while(c<'0'||c>'9') {
if(c=='-') f=-1;
c=getchar();
}
while(c>='0'&&c<='9') {
x=(x<<3)+(x<<1)+(c^48);
c=getchar();
}
return x*f;
}
const int N=1e5+50,M=2e5+50;
int head[N],nxt[M],to[M],W[M],num;
ll dis[N];
void add(int u,int v,int w) {
++num;nxt[num]=head[u];to[num]=v;W[num]=w;head[u]=num;
}
priority_queue<PII,vector<PII>,greater<PII> >q;
int main() {
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
int n=read(),m=read(),s=read();
for(int i=1;i<=m;i++) {
int u=read(),v=read(),w=read();
add(u,v,w);
}
memset(dis,0x3f,sizeof(dis));
dis[s]=0;
q.push({dis[s],s});
while(!q.empty()) {
int u=q.top().se;
if(dis[u]!=q.top().fir) {//寫法較奇怪,此處如果dis[u]!=q.top().fir,則dis[u]<q.top().fir,此時{dis[u],u}已經出佇列一次,因此此時不需要使用u節點更新
q.pop();
continue;
}q.pop();
for(int i=head[u];i;i=nxt[i]) {
int v=to[i];
if(dis[v]>dis[u]+W[i]) {
dis[v]=dis[u]+W[i];
q.push({dis[v],v});
}
}
}
for(int i=1;i<=n;i++) printf("%lld ",dis[i]);
return 0;
}
dijkstra 實際複雜度為 \(\text{O}(m\log n)\)
每個點只會被更新一次,每條邊只會更新其他點一次,因此複雜度為 \(\text{O}(m\log n^2)=\text{O}(2m\log n)\),所以複雜度為 \(\text{O}(m\log n)\)。
by lyk&yjx