首页 > 其他分享 >关于虚树

关于虚树

时间:2024-08-09 11:17:53浏览次数:11  
标签:top 栈顶 stk 关于 LCA 虚树 关键点

关于虚树

瞎扯

某些树上问题,给了巨多节点,而实际上它们之中只有小部分能做出贡献,其余都是些水军,为杀尽 OIers的脑细胞 做出努力

考虑重新种一棵树,浓缩信息,简化节点个数,于是产生了 虚树

大概是长这个样子:
红色结点是我们选择的关键点,即能够做出贡献的点。红色和黑色结点都是虚树中的点。黑色的边是虚树中的边。

因为任意两个关键点的 LCA 也是需要保存重要信息的,能够维持树的形态,所以我们需要保存它们的 LCA

显然,在保证爹不会变成儿子,儿子不会变成爹 爷爷也不行 的前提下,我们是可以随便把原有的点添到虚树中去的

你当然可以把原树所有的点都加到虚树中,只不过你这虚树建了跟建了一样

因此,为了方便,我们可以首先将 \(1\) 号节点加入虚树中,并且不会影响答案

构造

构造有两种方式,其中二次排序的方法常数较大,所以没写。才不会告诉你其实是因为我懒

本篇只介绍第二种,借助单调栈实现。

直接枚举所有关键点对,暴力求解 LCA 的时间复杂度显然不可接受。

我们可以将所有关键点先按 DFS 序排序,按顺序一个一个加到树里。刚开始树上只有 \(1\) 号点。

接下来,我们用一个栈维护在树上一条链上的所有点。这个栈内的所有点满足其 DFS 序单调递增。

每次要将下一个关键点(设为 \(u\))入栈前,求一下当前栈顶元素和这个关键点 \(u\) 的LCA \(p\),分讨:

  • 如果栈顶是 \(p\),则可以知道我们加入的关键点 \(u\) 和栈中的点在一条链上,直接将关键点加入栈中即可。如图

  • 如果此时栈顶不是 \(p\)(显然这时候 \(p\) 的 DFS 序比栈顶大,且 栈顶所在位置的子树业已处理完毕),说明 \(p\) 不在链上,将栈顶弹出,直到栈顶为 \(p\),此时插入关键点。
    弹栈的时候记得把他和他父亲的边连一下。

酱紫我们的虚树就种好了捏~

Code

int LCA(int x,int y){//树剖LCA
	while(topf[x]!=topf[y]){
		if(dep[topf[x]]<dep[topf[y]]) swap(x,y);
		x=f[topf[x]];
	}
	if(dep[x]<dep[y]) swap(x,y);
	return y;
}

bool cmp(int x,int y){
	return dfn[x]<dfn[y];
}

int stk[N],top;
void build(){
	sort(a+1,a+1+k,cmp);
	stk[top=1]=1;
	for(int i=1;i<=k;i++){
		if(top==1){
			stk[++top]=a[i];
		}
		int lca=LCA(a[i],stk[top]);
		if(lca==stk[top]) continue;
		while(top>1 && dfn[stk[top-1]]>=dfs[lca]){
			addnew(stk[top-1],stk[top]);
			top--;
		}
		if(lca!=stk[top]){
			addnew(lca,stk[top]);
			stk[top]=lca;
		}
		stk[++top]=a[i];
	}
	while(top>0){//别忘了把栈里的连边
		addnew(stk[top-1],stk[top]);
		top--;
	}
	return;
}

标签:top,栈顶,stk,关于,LCA,虚树,关键点
From: https://www.cnblogs.com/Elaina-0/p/18350221

相关文章

  • 关于C#的Dynamic调用方法前的一些准备的小Demo
    usingSystem;usingSystem.CodeDom.Compiler;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Reflection;usingSystem.Text;usingSystem.Threading.Tasks;namespaceConsoleApp1{publicclassTest{publicstaticTestT......
  • Linux 【关于 /proc目录详解】
    proc目录:ProcessInformationPseudo-filesystem:进程信息伪文件系统/proc目录并不包含实际的文件,而是提供了一个动态的视图,用于显示系统和进程相关的信息,甚至可以通过更改其中某些文件来改变内核的运行状态。其目的:用于管理和监控系统状态和进程信息/proc文件本身的大小显示......
  • Linux 【关于内核参数详解和优化】
    Linux内核参数是操作系统中用于调整和优化系统性能和行为的关键设置。Linux内核参数可以通过以下几种方式进行查看和修改:/proc/sys目录:大多数内核参数都可以在/proc/sys目录下找到,使用sysctl命令查看和设置这些参数。sysctl.conf文件:此文件通常位于/etc目录中,可以在系统启动......
  • 关于嵌套循环之深入理解
    关于嵌套循环之深入理解#外层循环遍历第一维(深度)fordepthinrange(len(cube)):#中层循环遍历第二维(行)forrowinrange(len(cube[depth])):#内层循环遍历第三维(列)forcolinrange(len(cube[depth][row])):print(cube......
  • 关于二分图上的最大匹配、最小点覆盖、最大独立集以及最大权闭合子图的联系
    没有点权和边权的时候,不讨论最大权闭合子图,最大匹配=最小点覆盖=点数-最大独立集最小点覆盖=点数-最大独立集:这个很好理解,考虑只有一条边的二分图的情况,点覆盖要求两个端点至少选一个,独立集要求两个端点最多选一个,是互补的关系,这意味着一个合法点覆盖的点集与一个合法独立集的......
  • 关于Qt使用msvc时安装了Windows SDK后还显示警告
    如果我们在安装Qt时没有选择SDK或者其他原因,你的套件前面就会有一个黄色的感叹号。但是当我们安装SDK之后,而且电脑重启之后,会发现还是这个鸟样当我点击编译器时,我发现是有的所以我想在kit这里是不是要自己配置呢?然后就大胆进行配置了下点击ok,然后创建一个项目发现......
  • Spring关于bean的一些基本知识
    在spring这座大厦中,去除掉最底部的核心(core)组件,那么最重要的无疑是bean和bean工厂。剩余是AOP、设计模式,更之上的就是各种组件:DATA,WEBMVC... 为了便于行文,这里把bean和bean工厂统称为bean。bean英文的意思是豆子。为了符合它的实际作用,本人把bean翻译为“缓存对象实例”,但......
  • 关于java连接数据库时提示异常java.sql.SQLException: No suitable driver found for
    当我们测试一个新的数据库服务时,需要使用对方提供jdbc驱动来连接数据库,有时候简单的写个demo去连接,发现提示异常:java.sql.SQLException:Nosuitabledriverfoundforjdbc:jdbc:nuuv://10.1.8.99:8832/xxoo比如有以下程序连接数据库测试:publicstaticvoidmain(String[]a......
  • keycloak~关于社区登录的过程说明
    keycloak将第三方登录(社区登录)进行了封装,大体主要会经历以下三个过程:打开社区认证页面,输入账号密码或者扫码,完成社区上的认证由社区进行302重定向,回到keycloak页面keycloak与社区完成一次oauth2授权码认证,通过社区返回的code来获取token,再通过token来获取社区上的用户信息,在这......
  • 关于在firewall防火墙无法阻止Docker 容器映射端口被外部访问问题的回顾
    这个问题是很早之前处理的,我自己已经没有印象了,今天同事拿了一个处理安全的文档来找我,上面赫然出现了我的名字,比较懵逼。。。这个问题的现象实际上是 docker映射的端口,通过firewalld 防火墙禁用端口不生效,外部还是能访问到,公司在进行安全扫描的时候总是被抓。。。。在firewall......