关于dij的一点疑问

P4779 【模板】单源最短路径(标准版)

Chancylaser @ 2022-08-13 21:53:19

突发奇想,发现了一个问题:

求助各位神犇,为什么第一份会T前三?

#include<bits/stdc++.h>
#define PII pair<int,int>
const int N=5e5+5,M=1e9; 
using namespace std;
int n,m,s;
int fst[N],nxt[N],to[N],sum[N];
int tot;
void add_edge(int u,int v,int w){
    nxt[++tot]=fst[u];
    fst[u]=tot;
    to[tot]=v;
    sum[tot]=w; 
}

int dist[N];
priority_queue<PII,vector<PII>,greater<PII> >dui;
bool rit[N];

void dijkstra(int p){
    for(int i=1;i<=n;i++) dist[i]=M;
    dist[p]=0;
    dui.push({0,p});

    while(dui.size()){
        while(rit[dui.top().second]) dui.pop();
        PII t=dui.top();

        int nw=t.second;dui.pop();
        rit[nw]=1;
        for(int i=fst[nw];i;i=nxt[i]){
            int t_o=to[i],w=sum[i];
            if(dist[nw]+w<dist[t_o]){
                dist[t_o]=dist[nw]+w;
                if(!rit[t_o])
                    dui.push({dist[t_o],t_o});
            }
        }
    }
    return;
}
int main(){
    scanf("%d%d%d",&n,&m,&s);
    for(int i=1;i<=m;i++){
        int u,v,w;
        scanf("%d%d%d",&u,&v,&w);
        add_edge(u,v,w);
    }

    dijkstra(s);
    for(int i=1;i<=n;i++)
        printf("%d ",dist[i]);
    return 0;
}
#include<bits/stdc++.h>
#define PII pair<int,int>
const int N=5e5+5,M=1e9; 
using namespace std;
int n,m,s;
int fst[N],nxt[N],to[N],sum[N];
int tot;
void add_edge(int u,int v,int w){
    nxt[++tot]=fst[u];
    fst[u]=tot;
    to[tot]=v;
    sum[tot]=w; 
}

int dist[N];
priority_queue<PII,vector<PII>,greater<PII> >dui;
bool rit[N];

void dijkstra(int p){
    for(int i=1;i<=n;i++) dist[i]=M;
    dist[p]=0;
    dui.push({0,p});

    while(dui.size()){
        PII t=dui.top();
        int nw=t.second; dui.pop();
        if(rit[nw]) continue;

        rit[nw]=1;
        for(int i=fst[nw];i;i=nxt[i]){
            int t_o=to[i],w=sum[i];
            if(dist[nw]+w<dist[t_o]){
                dist[t_o]=dist[nw]+w;
                if(!rit[t_o])
                    dui.push({dist[t_o],t_o});
            }
        }
    }
    return;
}
int main(){
    scanf("%d%d%d",&n,&m,&s);
    for(int i=1;i<=m;i++){
        int u,v,w;
        scanf("%d%d%d",&u,&v,&w);
        add_edge(u,v,w);
    }

    dijkstra(s);
    for(int i=1;i<=n;i++)
        printf("%d ",dist[i]);
    return 0;
}

by Wilson_Lee @ 2022-08-13 22:01:02

第一份要判一下堆是否为空


by Compound_Interest @ 2022-08-13 22:01:10

@signed 你出优先队列之后没有continue,优先队列优化的dijkstra会有冗余信息存在优先队列里面,冗余的还要扫一遍与他邻接的边导致超时,冗余的点存进去不会扫他的邻接边不会对答案产生贡献


by NightTide @ 2022-08-13 22:01:31

@signed 你第一份代码第 25 行改成:while(!dui.empty() && rit[dui.top().second]) dui.pop();


by ZhuMingYang @ 2022-08-13 22:02:09

@signed

while(rit[dui.top().second]) dui.pop();
=>
while(!dui.empty()&&rit[dui.top().second]) dui.pop();

by NightTide @ 2022-08-13 22:02:35

@signed 还要再在后面加一行:if(dui.empty()) break


|