#dijkstra+zkw线段树#洛谷 4779 洛谷 1339 【模板】单源最短路径(标准版)热浪

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sugar_free_mint/article/details/84589379

分析

首先为什么要说这种方法呢,因为根据模板,zkw线段树优化比STL堆快了一倍,所以说在此推荐我的热浪题解


代码

#include <cstdio>
#include <cctype>
#include <algorithm>
#define rr register
using namespace std;
const int inf=1e9+7;
struct node{int y,w,next;}e[200005];
int n,m,s,bas=1,k=1,ls[100001],w[270001],p[270001],dis[100001];
inline signed iut(){
    rr int ans=0; rr char c=getchar();
    while (!isdigit(c)) c=getchar();
    while (isdigit(c)) ans=(ans<<3)+(ans<<1)+c-48,c=getchar();
    return ans;
}
inline void add(int x,int y,int w){
    e[++k]=(node){y,w,ls[x]}; ls[x]=k;
}
inline void update(int x){
    w[x]=(w[x<<1]<w[x<<1|1])?w[x<<1]:w[x<<1|1];
    p[x]=(w[x<<1]>w[x<<1|1])?p[x<<1|1]:p[x<<1];
}
inline void print(int ans){
    if (ans>9) print(ans/10);
    putchar(ans%10+48);
}
signed main(){
    n=iut(); m=iut(); s=iut();
    for (rr int i=1;i<=m;++i){
        rr int x=iut(),y=iut(),w=iut();
        add(x,y,w);
    }
    while ((bas<<=1)<n+2);
    fill(w+1,w+2+(bas<<1),inf); fill(dis+1,dis+1+n,inf);
    fill(p+1,p+2+(bas<<1),inf); w[s+bas-1]=dis[s]=0;
    for (rr int i=0;i<n;++i) p[bas+i]=i+1;
    for (rr int i=bas-1;i;--i) update(i);
    while (w[1]<inf){
        rr int x=p[1],y=p[1]+bas-1; w[y]=inf;
        for (y>>=1;y;y>>=1) update(y);
        for (rr int i=ls[x];i;i=e[i].next)
        if (dis[e[i].y]>dis[x]+e[i].w){
            dis[e[i].y]=dis[x]+e[i].w; rr int t=e[i].y+bas-1;
            for (w[t]=dis[e[i].y],t>>=1;t;t>>=1) update(t);
        }
    }
    for (rr int i=1;i<=n;++i) print(dis[i]),putchar(i==n?10:32);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/sugar_free_mint/article/details/84589379