首页 > 其他分享 >虚树

虚树

时间:2022-09-22 18:57:00浏览次数:41  
标签:emplace back tp st lca 虚树

虚树是一种神奇的算法,它的具体思想为在一棵较为庞大的树当中,我们可能并不需要考虑该树上的所有节点,而是只需要考虑其中的一部分的话,我们可以使用这些点组建一棵虚树。虚树仍可以维护这些点之间的祖孙,兄弟等关系。一般来说,多次询问且\(\Sigma\)点数复杂度可接受为虚树的提示。

如何组建一棵虚树?

首先我们先抛出一个结论,将这些需要考虑的节点按dfs序排序,虚树需要的点仅为这些点及两两相邻的节点的lca。

证明略

好了,我们现在已经证毕这个结论了,具体的建树方法如下:
1.首先,我们需要维护一个栈,这个栈无论何时都是一条链(栈顶为最深的节点),我们先把根节点入栈
2.我们一次考虑已经按照dfs序排列好的点,对于一个新点,我们找到他与栈顶的lca
3.我们首先将栈顶依次弹出,并每次将弹出的点与新栈顶连边,直到栈顶深度比lca的小
4.我们把lca和新点一次入栈(注:若有重复点则不在入栈)
5.当我们考虑完所有点之后,我们把栈中的所有点依次连边

点击查看代码
scanf("%d",&k);
	for(int i=1;i<=k;++i) scanf("%d",&h[i]),point[h[i]]=1;
	sort(h+1,h+k+1,[](int a,int b){return dfn[a]<dfn[b];});
	st[tp=1]=1;
	for(int i=1;i<=k;++i){
		int L=lca(st[tp],h[i]);
		while(dep[st[tp-1]]>dep[L]){
			E[st[tp-1]].emplace_back(st[tp]);
			E[st[tp]].emplace_back(st[tp-1]);
			tp--;
		}	
		if(L==st[tp]){st[++tp]=h[i];continue;}
		E[st[tp]].emplace_back(L);
		E[L].emplace_back(st[tp]);
		--tp;
		if(L!=st[tp]) st[++tp]=L;
		st[++tp]=h[i];
	}
	for(int i=1;i<tp;++i) 
		E[st[i]].emplace_back(st[i+1]),E[st[i+1]].emplace_back(st[i]);
	

标签:emplace,back,tp,st,lca,虚树
From: https://www.cnblogs.com/goldenwalnut/p/16720503.html

相关文章

  • 虚树
    一种大树变小树的方法。大概就是只保留题目要求的关键点和其他一些统计答案必须的点,把剩余的所有点从树上砍掉。原理是维护一条最右链(就是我们扫到的最右边的一条链,它左边......
  • dfs序 括号序 欧拉序 树上莫队 虚树建立 傻傻分不清
    括号序进加一次,出加一次,显然最后得到的序列只有\(2n\)个点。voiddfs(intx){ in[x]=++tot; for(y)dfs(y); out[x]=++tot;}显然我们希求将树上路径表示为区......