最短路——分层图

https://www.luogu.org/problem/P1948

LuoguP1948 电话线

K次免费机会-->每个点(i)拆成(i,k),表示使用了k次免费机会后的i;

于是就将平常的一张图(二维)转换为立体图(三维),但实现上还是二维的

每层跟平常一样建边,然后再在两层之间建图作为联系,即免费边。

最后看每层的(n,k)点的dis(使用了k次机会后到n的花费);

dis[v]>dis[u]+val[i]根据题改为dis[v]>max(dis[u],val[i]);

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10,M=1e7+10,INF=1e9;
int n,p,k;
int head[N],nex[M*2],to[M*2],val[M*2],tot;
void build(int u,int v,int w){tot++;nex[tot]=head[u];to[tot]=v;val[tot]=w;head[u]=tot;}
bool vis[N]; int dis[N]; priority_queue<pair<int,int> >q; void spfa() { for(int i=1;i<=n*(k+1);i++)dis[i]=INF; q.push(make_pair(-0,1)); dis[1]=0; while(!q.empty()) { int u=q.top().second;q.pop(); if(vis[u])continue;vis[u]=1; for(int i=head[u];i;i=nex[i]) { int v=to[i],w=max(dis[u],val[i]); if(dis[v]>w) { dis[v]=w; q.push(make_pair(-w,v)); } } } } int main() { scanf("%d%d%d",&n,&p,&k); for(int u,v,w,i=1;i<=p;i++) { scanf("%d%d%d",&u,&v,&w); for(int j=0;j<=k;j++) { build(u+j*n,v+j*n,w); build(v+j*n,u+j*n,w); } for(int j=0;j<k;j++) { build(u+j*n,v+(j+1)*n,0); build(v+j*n,u+(j+1)*n,0); } } spfa(); int ans=INF; for(int i=0;i<=k;i++) { ans=min(ans,dis[n+i*n]); } if(ans!=INF)printf("%d",ans); else printf("-1"); } 作者:yfxJ518 链接:https://www.acwing.com/activity/content/code/content/124992/ 来源:AcWing 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

猜你喜欢

转载自www.cnblogs.com/fengJ518/p/11628114.html
今日推荐