分层图最短路板子
题目链接: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;
}

浙公网安备 33010602011771号