分层图最短路板子

题目链接:https://www.luogu.com.cn/problem/P4568

题意:

给定n个节点,m条边的无向带权图,可以最多免费经过k条边。给定起点和终点,求最短路。

建分层图跑最短路:

建立分层图,相当于再建立相同的另外k个图,然后上面图的节点可以以0边权转移到下面图的对应节点

rep(i,1,m){
        int a,b,c;cin>>a>>b>>c;
        e[a].pb({b,c});e[b].pb({a,c});
        for(int j=1;j<=k;j++){
            e[a+j*n].pb({b+j*n,c});
            e[b+j*n].pb({a+j*n,c});
            e[a+(j-1)*n].pb({b+j*n,0});
            e[b+(j-1)*n].pb({a+j*n,0});
        }
    }

无负边权,直接用dj跑最短路
需要注意空间问题。

vector<pii>e[maxn];
int dis[maxn];
int vis[maxn];
priority_queue<pii>q;
void dj(int st){
    // memset(dis,inf,sizeof dis);
    for(int i=0;i<=5e5;i++){
        dis[i]=llmax;
    }
    dis[st]=0;
    q.push({0,st});
    while(q.size()){
        pii now=q.top();q.pop();
        int u=now.se,d=-now.fi;
        if(vis[u])continue;
        vis[u]=1;
        for(pii x:e[u]){
            int v=x.fi,distance=x.se;
            if(distance+dis[u]<dis[v]){
                dis[v]=distance+dis[u];
                q.push({-dis[v],v});
            }
        }
    }
}
void solve(){
    int n,m,k;cin>>n>>m>>k;
    int st,ed;cin>>st>>ed;
    rep(i,1,m){
        int a,b,c;cin>>a>>b>>c;
        e[a].pb({b,c});e[b].pb({a,c});
        for(int j=1;j<=k;j++){
            e[a+j*n].pb({b+j*n,c});
            e[b+j*n].pb({a+j*n,c});
            e[a+(j-1)*n].pb({b+j*n,0});
            e[b+(j-1)*n].pb({a+j*n,0});
        }
    }
    dj(st);
    int ans=llmax;
    ans=min(ans,dis[ed]);
    for(int i=1;i<=k;i++){
        ans=min(ans,dis[ed+i*n]);
    }
    cout<<ans<<endl;
}
posted @ 2025-05-21 10:31  Marinaco  阅读(8)  评论(0)    收藏  举报
//雪花飘落效果