分层图学习随笔

前言

一般来说,分层图完全可以用魔改dij做(不知道是我太狭隘了),反正我在没学分层图之前,分层图的套路题都是用二维dij类似dp写的,但是觉得分层图很有意思,就学了一下

放道例题(个人觉得分层图是个套路,直接看题分析学习即可)

初来乍到,像我这样的蒟蒻直接开题(jie ,然后发现自己理解也不理解(大雾
再看了几遍,我觉得分层图可以总结为一句话(针对此题):把一个点强行拆分为k个,原图层代表使用0次升级路的机会,其他的图分别表示使用了1次、2次…k次升级路的机会

我当时顿悟,分层图每一层其实都是一样的,不一样的点就在于每层的连接✌

我悟出来的就是,如果你走到分层图第i层 ( 2 ≤ i ≤ k + 1 ) \big(2 \leq i\leq k+1 \big) (2ik+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;
}

额,本人水平太菜,讲不出什么东西来,但是我觉得分层图这种东西套路性比较强,多练练就会了😍

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值