Kruskal 重构树

news/2024/9/20 7:52:45/文章来源:https://www.cnblogs.com/HaneDaCafe/p/18325982

算法介绍

Kruskal 重构树用于快速判断节点的连通性.

考虑到,假如两个节点是联通的,则他们之间总会有一条边被选入最小生成树内,因此他们在最小生成树内也是联通的. 也就是说,我们可以通过求最小生成树来减少我们判断联通需要的边数.

Kruskal 重构树的思想是这样的:假如有一条生成树边 \((x,y)\),则断开 \((x,y)\),新建一个虚电 \(i\),连接 \((x,i),(y,i)\),在这样操作后,因为原生成树即为一棵树,因此新构成的图也是一棵树,并且树上任意一点的子树中的所有节点总是可达的. 这个操作可以在求生成树时同时进行.

对于带权的边,我们可以把边权直接放到点上. 注意到这样构造出来的重构树一定是二叉堆. 并且任意两点路径边权最大值为重构树上LCA的点权.

为什么是最大值?考虑到我们构建最小生成树的过程,最大的边一定会后选. 在考虑我们构建重构树的过程,后选的边总是作为新的父节点,因此两点的 LCA 即为两点间路径中最后选的那一个,即边权最大值.

注意到这一块可能是需要爆改的,改这个主要使用改最小生成树来实现,学长说跑什么生成树是需要变通的,比如要求最小边权就需要跑最大生成树,有时候还需要跑特殊生成树,只不过这个算法的思想是借助的 Kruskal 的,所以我们用最小生成树当例子.

首先新建 \(n\) 个集合,每个集合恰有一个节点,点权为 \(0\)

每一次加边会合并两个集合,我们可以新建一个点,点权为加入边的边权,同时将两个集合的根节点分别设为新建点的左儿子和右儿子。然后我们将两个集合和新建点合并成一个集合。将新建点设为根

此处模板使用 \(\gt n\) 的点作为虚点.

void Kruskal(){for(int i=1;i<=n;i++){fa[i]=i;}int cnt=0;sort(e+1,e+n+1);for(int i=1;i<=m;i++){int x=e[i].x, y=e[i].y, w=e[i].w;int fx=find(x),fy=find(y);if(fx^fy){val[++cnt+n]=w;fa[fx]=fa[fy]=fa[cnt+n]=now;e[cnt+n].push_back({fx,1});e[cnt+n].push_back({fy,1});}}
}

CF1706E Qpwoeirut and Vertices

这个题涉及到了重构树求最值的问题,写了比较有启发意义的爆改线段树

此题可以将时间戳设计成点权,考虑到重构树的特殊性质,我们可以将其按时间戳全部联通,根据任意两点路径边权最大值为重构树上LCA的点权,此题我们需要求的正好就是边权最大值,因此直接维护树上 LCA 即可. 取最值可以用 st 表或线段树.

这里没排序是因为时间戳是有序的,用的线段树来维护,更新子节点节点最大权值的时候也可以直接 LCA 解决,比较方便,只是常数比 LCA 大.

#include<bits/stdc++.h>
using namespace std;
int n,m,q,tot;
namespace dsu{int fa[300001];inline void clear(){for(register int i=1;i<=n+m;++i){fa[i]=i;}}inline int find(int id){if(id==fa[id]) return id;fa[id]=find(fa[id]);return fa[id]; }
}
vector<int>e[300001];
namespace lca{int fa[20][300001],deep[300001];inline void dfs(int now){for(int i=1;i<=19;++i){fa[i][now]=fa[i-1][fa[i-1][now]];}for(int i:e[now]){deep[i]=deep[now]+1;fa[0][i]=now;dfs(i);}}inline void prework(){for(register int i=1;i<=19;++i){for(register int j=1;j<=n+m;++j){fa[i][j]=fa[i-1][fa[i-1][j]];}}}inline int lca(int x,int y){if(deep[x]<deep[y]) swap(x,y);for(register int i=19;i>=0;--i){if((deep[x]-deep[y])>=(1ll<<i)){x=fa[i][x];}}if(x==y) return x;for(register int i=19;i>=0;--i){if(fa[i][x]!=fa[i][y]){x=fa[i][x];y=fa[i][y];}}return x==y?x:fa[0][x];}
}
namespace stree{#define tol (id*2)#define tor (id*2+1)#define mid(x,y) mid=((x)+(y))/2struct tree{int l,r,w;}t[400001];inline void build(int id,int l,int r){t[id].l=l,t[id].r=r;if(l==r){t[id].w=l;return;}int mid(l,r);build(tol,l,mid);build(tor,mid+1,r);t[id].w=lca::lca(t[tol].w,t[tor].w);}inline int ask(int id,int l,int r){if(t[id].l==l and t[id].r==r) return t[id].w;int mid(t[id].l,t[id].r);if(r<=mid) return ask(tol,l,r);if(l>=mid+1) return ask(tor,l,r);return lca::lca(ask(tol,l,mid),ask(tor,mid+1,r));}
}
namespace hdk{namespace Iter{void cout(std::vector<int> &_v,int _from,int _to,char _devide){std::vector<int>::iterator iter;std::vector<int>::reverse_iterator riter;if(_from<_to){for(iter=_v.begin()+_from;iter!=_v.begin()+_to;++iter){std::cout<<*iter<<_devide;}}else{for(riter=_v.rbegin()+_to;riter!=_v.rbegin()+_from;++riter){std::cout<<*riter<<_devide;}}}}template<typename T>void memset(T a[],int _val,int _size){if(_val==0){for(T* i=a;i<=a+_size-1;++i) *i&=0;return;}for(T* i=a;i<=a+_size-1;++i)*i=_val;}namespace fastio{void rule(bool setting=false){std::ios::sync_with_stdio(setting);}inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-'){f=-1;}ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}return x*f;}inline int read(int &A){A=read();return A;}inline char read(char &A){A=getchar();return A;}inline void write(int A){if(A<0){putchar('-');A=-A;}if(A>9){write(A/10);}putchar(A%10+'0');}inline void write(long long A){if(A<0){putchar('-');A=-A;}if(A>9){write(A/10);}putchar(A%10+'0');}inline void write(char A){putchar(A);}inline void space(){putchar(' ');}inline void endl(){putchar('\n');}#define w(a) write(a)#define we(a) write(a);endl()#define ws(a) write(a);space()}
}
using namespace hdk::fastio;
int main(){
//	freopen("lagrange1.in","r",stdin);
//	freopen("hdk.out","w",stdout);int cases;read(cases);while(cases--){read(n);read(m);read(q);tot=0;dsu::clear();for(int i=1;i<=n+m;++i){e[i].clear();}for(register int i=1;i<=m;++i){int x,y;read(x);read(y);int fx=dsu::find(x),fy=dsu::find(y);if(fx==fy) continue;e[i+n].push_back(fx);e[i+n].push_back(fy);dsu::fa[fx]=dsu::fa[fy]=i+n;tot=i+n;}lca::deep[tot]=1;lca::dfs(tot);//	lca::prework();stree::build(1,1,n);for(register int i=1;i<=q;++i){int l,r;l=read();r=read();if(l^r){ws(stree::ask(1,l,r)-n);}else{putchar('0');putchar(' ');}}endl();}
}

[NOI2018] 归程

正在写,一会发

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/772121.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2024牛客多校A Bit Common A Bit More Common

牛客2024年多校第一场AB题题解,新手向A Bit Common 时间限制:3s(C++/C) / 6s 内存限制:1048576K(C++/C) / 2097152K 题目描述 Given two integers \(n\) and \(m\), among all the sequences containing \(n\) non-negative integers less than \(2^m\), you need to count…

2024中国工业互联网安全大赛智能家电行业赛道选拔赛

流量分析的附件链接: https://pan.baidu.com/s/1UlWzfmsmRsZTR56FzXLuEg?pwd=6666 提取码: 6666 恶意攻击流量 描述:应用系统被植入了恶意后门,并从流量中识别其中的flag,提交格式:fag{XXXXXXXX} 追踪这个流量解码过滤或者工具一把梭flag{39084EEF2D28E941F53E4A1AA1FA6766…

java 06

输入:引入scanner import java.util.Scanner Scanner scanner=new Scanner(System.in) String name=mySanneer.nextInt()//输入内容 在命令框输入Java input 进制:十进制转二进制:不断除以2最后将余数倒着拍;转8转16相似; 位运算: 1>>2:1向右位移两位;1<<…

rockchip --- 更新固件

使用电脑上位机更新固件 uboot 运行过程,会判断 boot mode 是 normal 还是 loader,如果是 normal 则正常加载 kernel 运行,如果是 loader,则等待从 usb 获取固件上位机点击切换到 loader,会发送指令给设备,让设备改写 boot mode 标志,关机再重启,进入 uboot,读取 boot…

24金砖网络安全

ez_raw-1 题目描述:小明在电脑上画了一幅图,这幅图的内容是什么,请提交其内容的md5值(32位小写) vol查看信息查看进程看到一个绘图的软件,提取出来查看一下文件类型改后缀名之后用gimp编辑ez_raw-2 题目描述:小明电脑的登录密码是什么使用插件一把嗦了 ez_raw-3 题目描述…

24矩阵杯线下赛

24矩阵杯线下赛是在6月26日-6月27日最终排名在27名 比赛内容是内网渗透,基本上都是用工具扫 签了保密协议,题目不让放出来 这个比赛是由360安全举办的,包路费,酒店费,就感觉挺好的比赛结束之后,晚上是聚会,有抽奖,我抽到了贴纸和U盘,运气爆棚。

Excel常用的一些命令和功能

excel单元格删除光标后面的数字,用Ctrl+Del快捷键; 删除多个单元格里面的值,用Ctrl+Del快捷键,也可以扩大范围框选;智能排序:在单元格里输入星期一,把光标放在单元格的右下方,等到出现+就可以向右和向下拖动,如图:都可以拖动,因为这些已经提前配置好了,如果没有配…

VMware Fusion Pro 虚拟机 免费了附最新版 13.5.2-23775688 下载地址

VMware Fusion Pro 可以帮助用户在 Mac 上安装 Windows、Linux 等多种操作系统,最重要的是无需重启电脑切换系统,可以和 MacOS 系统同时运行,就类似于 MacOS 安装了一个应用。对于家庭用户来说足够简单,对于 IT 专业人员,开发人员和企业来说足够强大。 VMware Fusion Pro …

2024LitCTF

secret 这首音乐好听,听完了,中间有段杂音去AU看看 中间有一段藏了东西,放大出flag了flag{Calculate_Step_By_Step} 原铁,启动! 解压出来是一张二维码扫出来是原神去010看看看到有压缩包,提取出来得到一个压缩包,里面是四张图片去网站上合并LitCTF{Genshin_St@rt!!} 涐…

虚幻五 学习制作多人在线游戏 (二)

在新建项目里面 可以看到运行按钮旁边有三个点 点击后 可以看到玩家数量 可以按照自己的需求更改 并且将网络模式改为 以客户端运行 打开角色蓝图 在角色蓝图中添加以下信息 其中Open 后面是 自己的IP地址 在菜单栏 单机文件 选择 新建关卡 新建一个默认关卡就可以了 在运行…

【待做】【AI+安全】数据集:APT攻击数据集

APT攻击数据集 非常棒的两个数据集,APT样本HASH值和APT报告。 https://github.com/RedDrip7/APT_Digital_Weaponhttps://github.com/kbandla/APTnotes下载推荐: https://virusshare.com/https://virusshare.com/https://app.any.run/

EMS/PCS/BMS/充电桩/逆变器新能源设备处理器选型-米尔嵌入式

随着全球对可持续发展的日益关注,新能源技术作为替代传统能源的重要选择,正迅速发展并深入各个领域。在这一技术革新的浪潮中,嵌入式技术作为关键的智能化解决方案,正在为新能源行业的发展注入新的动力和创新。本文旨在为新能源行业的开发者解决嵌入式处理器选型难题。 1.米…