前言
一般来说,分层图完全可以用魔改dij做(不知道是我太狭隘了),反正我在没学分层图之前,分层图的套路题都是用二维dij类似dp写的,但是觉得分层图很有意思,就学了一下
放道例题(个人觉得分层图是个套路,直接看题分析学习即可)
初来乍到,像我这样的蒟蒻直接开题(jie ,然后发现自己理解也不理解(大雾
再看了几遍,我觉得分层图可以总结为一句话(针对此题):把一个点强行拆分为k个,原图层代表使用0次升级路的机会,其他的图分别表示使用了1次、2次…k次升级路的机会
我当时顿悟,分层图每一层其实都是一样的,不一样的点就在于每层的连接✌
我悟出来的就是,如果你走到分层图第i层
(
2
≤
i
≤
k
+
1
)
\big(2 \leq i\leq k+1 \big)
(2≤i≤k+1),说明你肯定前面通过0的高速公路下到这一层, 举个例子,到达第三层就是使用两次修改次数
这也就是为什么分层图有
k
+
1
k+1
k+1 层
注意一点:数组要乘上 k k k的最大范围,要不你会看到一片喜人的紫色(别问我怎么知道的
#include<bits/stdc++.h>
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;
const int N=3e5+10,M=N<<5;
int head[N],ver[M],nxt[M],val[M],idx;
int n,m,k,dis[N],vis[N];
void add(int u,int v,int w){
ver[idx]=v,val[idx]=w,nxt[idx]=head[u],head[u]=idx++;
}
struct node{
int d,id;
bool operator<(const node&h) const{return d>h.d;}
};
void dijkstra(){
memset(dis,0x3f,sizeof dis);
priority_queue<node> q;
dis[1]=0;
q.push({0,1});
while(!q.empty()){
node tmp=q.top();q.pop();
int x=tmp.id,d=tmp.d;
if(vis[x]) continue;
vis[x]=1;
for(int i=head[x];~i;i=nxt[i]){
int y=ver[i],w=val[i];
if(dis[y]>dis[x]+w){
dis[y]=dis[x]+w;
q.push({dis[y],y});
}
}
}
}
int main(){
memset(head,-1,sizeof head);
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=m;++i){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
add(u,v,w),add(v,u,w);
for(int j=1;j<=k;++j){
add(n*j+u,n*j+v,w),add(n*j+v,n*j+u,w);//把下边的每一层都把这条边建上
add(n*(j-1)+u,n*j+v,0),add(n*(j-1)+v,n*j+u,0);
}
}
dijkstra();//建完分层图后就把它当做正常图跑dij即可
int ans=INF;
for(int i=0;i<=k;++i)
ans=min(ans,dis[i*n+n]);//总共有k+1一层
printf("%d\n",ans);
return 0;
}
额,本人水平太菜,讲不出什么东西来,但是我觉得分层图这种东西套路性比较强,多练练就会了😍