首页 > 其他分享 >Kruskal 重构树学习笔记+杂题

Kruskal 重构树学习笔记+杂题

时间:2024-11-13 09:09:59浏览次数:1  
标签:重构 瓶颈 res Kruskal 路径 最小 int 杂题 边权

图论系列:

前言:

相关题单:戳我

一.最小瓶颈路

唉,前面4个题单里其实有不少题是最小瓶颈路的做法啊。讲解摘自 wiki 。

1.定义

无向图 \(G\) 中 \(x\) 到 \(y\) 的最小瓶颈路是这样的一类简单路径,满足这条路径上的最大的边权在所有 \(x\) 到 \(y\) 的简单路径中是最小的。(对于下面这张图, \(2 \to 3\) 的最小瓶颈路就是 \(2 \to 1 \to 5 \to 3\) ,此时经过路径最大值为 \(4\))。

相当于你需要一定的等级才能走一条边(这就是边权),问你需要从 \(x\) 走到 \(y\) 所需要的最小等级。将所有小于等于此等级的边添加如图中,图中每一条 \(x \to y\) 的路径都是最小瓶颈路。

2.性质

根据最小生成树定义,\(x\) 到 \(y\) 的最小瓶颈路上的最大边权等于最小生成树上 \(x\) 到 \(y\) 路径上的最大边权。虽然最小生成树不唯一,但是每种最小生成树 \(x\) 到 \(y\) 路径的最大边权相同且为最小值。也就是说,每种最小生成树上的 \(x\) 到 \(y\) 的路径均为最小瓶颈路。

但是,并不是所有最小瓶颈路都存在一棵最小生成树满足其为树上 \(x\) 到 \(y\) 的简单路径。

3.应用

由于最小瓶颈路不唯一(如上图中最小瓶颈路还可以是 \(2 \to1 \to 5\to 4 \to 3\) ),一般情况下会询问最小瓶颈路上的最大边权。也就是说,我们需要求最小生成树链上的 max,倍增、树剖都可以解决。

给一道板子题,先将最小生成树建出来后判断链上边权最大值即可(注意可能最后图可能不连通,可能会生成一个最小生成树森林)。

代码:

//采用的是树剖+倍增求解
const int M=1e3+5,N=1e5+5;
int n,m,q;
int fax[M],vis[M],deep[M],fa[M][19],dis[M][19];

struct node{
	int u,v,w;
	inline bool operator <(const node o) const
	{
		return w<o.w;
	}
};node e[N];

int cnt=0;
struct Edge{
	int to,next,val;
};Edge p[N<<1];
int head[M];
inline void add(int a,int b,int c)
{
	++cnt;
	p[cnt].next=head[a];
	head[a]=cnt;
	p[cnt].to=b;
	p[cnt].val=c;
}
inline int find(int x)
{
	if(x!=fax[x]) fax[x]=find(fax[x]);
	return fax[x];
}

inline void dfs(int u,int f)
{
	fa[u][0]=f,deep[u]=deep[f]+1,vis[u]=1;
	for(int i=head[u];i!=0;i=p[i].next)
	{
		int v=p[i].to;
		if(v==f) continue;
		dis[v][0]=p[i].val;
		dfs(v,u);
	}
}

inline int lca(int x,int y)
{
	if(deep[x]<deep[y]) swap(x,y);
	int c=deep[x]-deep[y],res=0;
	for(int i=0;i<=18;++i)
	{
		if(c&(1<<i)) res=max(res,dis[x][i]),x=fa[x][i];
	}
	for(int i=18;i>=0;--i)
	{
		if(fa[x][i]!=fa[y][i])
		{
			res=max(res,max(dis[x][i],dis[y][i]));
			x=fa[x][i],y=fa[y][i];
		}
	}
	if(x==y) return res;
	res=max(res,max(dis[x][0],dis[y][0]));
	return res;
}

signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	cin>>n>>m>>q;
	for(int i=1;i<=n;++i) fax[i]=i;
	for(int i=1;i<=m;++i) cin>>e[i].u>>e[i].v>>e[i].w;
	sort(e+1,e+m+1);
	for(int i=1,x,y;i<=m;++i)
	{
		x=find(e[i].u),y=find(e[i].v);
		if(x==y) continue;
		fax[x]=y;
		add(e[i].u,e[i].v,e[i].w),add(e[i].v,e[i].u,e[i].w);
	}
	for(int i=1;i<=n;++i) if(!vis[i]) dfs(i,0);
	for(int j=1;j<=18;++j)
	{
		for(int i=1;i<=n;++i)
		{
			fa[i][j]=fa[fa[i][j-1]][j-1];
			dis[i][j]=max(dis[i][j-1],dis[fa[i][j-1]][j-1]);
		}
	}//倍增处理
	int x,y;
	while(q--)
	{
		cin>>x>>y;
		if(find(x)!=find(y)) cout<<"-1\n";
		else cout<<lca(x,y)<<"\n";
	}
	return 0;
}

二.Kruskal 重构树

1.定义:

标签:重构,瓶颈,res,Kruskal,路径,最小,int,杂题,边权
From: https://www.cnblogs.com/call-of-silence/p/18543063

相关文章

  • 揭秘!Vue3.5响应式重构如何让内存占用减少56%
    前言Vue3.5版本又将响应式给重构了,重构后的响应式系统主要有两部分组成:双向链表和版本计数。我们在前两篇文章中我们已经讲过了双向链表和版本计数,这篇文章我们来讲讲为什么这次重构能够让内存占用减少56%。欧阳年底也要毕业了,加入欧阳的面试交流群(分享内推信息)、高质量vue......
  • 并查集+最小生成树 学习笔记+杂题 2
    图论系列:前言:相关题单:戳我算法讲解:戳我CF1829ETheLakes给定一张\(n*m\)的矩阵,询问正整数四联通块权值和的最大值。并查集维护即可,记录一下集合内的点的权值和。代码:constintM=1005;intT,n,m,ans;inta[M][M],fa[M*M],siz[M*M];intfx[5]={0,1,-1,0,0};intfy[5]......
  • 「杂题乱刷2」CF1288E
    题目链接CF1288EMessengerSimulator解题思路发现向前移的部分普通维护比较困难,因此我们考虑通过某种方式来维护这个东西。考虑建立\(m\)个虚点来维护,每次询问都将实点移至虚点去。这里求答案我们需要支持单点加,区间求和,可以用树状数组轻松维护。参考代码#include<bits/s......
  • 「杂题乱刷2」CF1219G
    题目链接CF1219GHarvester解题思路就是个嗯分讨题。发现最终选择的方案总共就以下五种情况:选\(4\)行\(0\)列。选\(3\)行\(1\)列。选\(2\)行\(2\)列。选\(1\)行\(3\)列。选\(0\)行\(4\)列。对于第一,五种情况,直接取每行或每列的前四大值......
  • 「杂题乱刷2」CF1354E
    题目链接CF1354EGraphColoring(*2100)解题思路发现这个东西就是类似于二分图染色的东西。因为\(2\)只能和\(1,3\)链接。其余种类的点都不能连接。不妨把\(1,3\)都看成同一个点放到最后处理。那么我们就相当于是要找到一种方案使得选择每个联通快的黑点或白点,使得最......
  • 「杂题乱刷2」CF1370F2
    题目链接CF1370F2TheHiddenPair(HardVersion)(*2700)题目描述真的很难吗?我们首先考虑找出第一个特殊点。我们可以先求出这两个点路径中的任意一个点。发现询问\(1\simn\)就使我们需要的询问、接下来以这个路径中的一个点为根来确定每个节点的深度。接下来考虑二......
  • 并查集+最小生成树 学习笔记+杂题 1
    图论系列:前言:相关题单:戳我算法讲解:戳我代码可能过多啊,到时候页面别卡死了,所以就把代码最前面的缺省源删了(反正就是几个头文件/defineintlonglong,自己加一下即可)。并查集记得初始化,最小生成树记得排序。P3367【模板】并查集板子题,给定\(n\)个元素,有2种操作,一种合并,......
  • 「杂题乱刷2」P11267
    题目链接P11267【MX-S5-T1】王国边缘解题思路先考虑对于\(1\simn\)中的每一个点往后跳\(1\)次会跳的距离。那么为什么只用处理\(1\simn\)这些点而不去处理其余的点往后跳的距离呢?我们可以发现,由于字符串是无线循环的,所以对于位置模\(n\)的结果相同时,那么往后跳......
  • 双连通分量学习笔记+杂题
    图论系列:前言:もしも明日がくるのならあなたと花を育てたいもしも明日がくるのならあなたと愛を語りたい走って笑って転んで相关题单:https://www.luogu.com.cn/training/641352一.割点与桥双连通分量是针对无向图来说的,有向图是强连通分量。在了解双连通分量之前需要先......
  • c++ Kruskal 最小生成树 (MST) 算法(Kruskal’s Minimum Spanning Tree (MST) Algorith
            对于加权、连通、无向图,最小生成树(MST)或最小权重生成树是权重小于或等于其他所有生成树权重的生成树。Kruskal算法简介:        在这里,我们将讨论Kruskal算法来查找给定加权图的MST。         在Kruskal算法中,按升序对给定图的所有......