原本以为K-D Tree比虚树难,但是后来发现虚树反而难理解一些。主要是关于找LCA的问题。

假如我们有一些点是一定要在虚树里的,那么需要保证他们任意两点的LCA也在虚树里,否则树的结构就改变了。

那么就需要用到dfs序了。

我们求得每个点的dfs序,然后把这些点按dfs序排序,那么他们所有的LCA肯定是排序后某相邻两点的LCA。这个是可以证明的,我就不证了。

然后找到LCA之后就是找每个节点的虚树父亲问题了,把找到的新节点(就是找到的LCA)与原来所有节点一起按照dfs序再排一次序,因为我们可以在初始化时找出每个点所在子树的最大最小时间戳,所以可以维护一个栈然后判断当前节点是否为栈内节点的原图中的子孙,若不是就弹栈,否则就是我们要找的父亲。

模板题链接

//Serene
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<set>
using namespace std;
const long long maxn=250000+10,INF=2e9;
long long n,m,mi[20];long long dp[maxn],len[maxn],node[maxn],zz[maxn];
int vis[maxn],fath[maxn];long long aa;char cc;
long long read() {aa=0;cc=getchar();while(cc<'0'||cc>'9') cc=getchar();while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();return aa;
}int fir[maxn],nxt[2*maxn],to[2*maxn];long long v[2*maxn],e=0;
void add(int x,int y,int z) {to[++e]=y;nxt[e]=fir[x];fir[x]=e;v[e]=z;to[++e]=x;nxt[e]=fir[y];fir[y]=e;v[e]=z;
}int fa[maxn][20],id[maxn],end[maxn],dep[maxn],tot,maxd;
void dfs(int pos,int d,long long minnum) {dep[pos]=d;id[pos]=++tot;len[pos]=minnum;maxd=max(maxd,d);for(int y=fir[pos];y;y=nxt[y]) {if(to[y]==fa[pos][0]) continue;fa[to[y]][0]=pos;dfs(to[y],d+1,min(v[y],minnum));}end[pos]=tot;
}bool cmp(const int x,const int y) {return id[x]<id[y];
}int getlca(int x,int y) {if(dep[x]!=dep[y]) {if(dep[x]<dep[y]) swap(x,y);int cha=dep[x]-dep[y];for(int i=18;i>=0;--i) if(mi[i]<=cha){cha-=mi[i]; x=fa[x][i];if(!cha) break;}}int xx,yy,z;while(x!=y) {xx=x; yy=y; z=0;while(xx!=yy) {x=xx; y=yy;xx=fa[xx][z];yy=fa[yy][z];z++;}if(z==1) { x=xx; y=yy; }}return x;
}int main() {n=read();int x,y,z,xx;for(int i=1;i<n;++i) {x=read();y=read();z=read();add(x,y,z);}dfs(1,1,INF);mi[0]=1;for(int i=1;i<=18;++i) mi[i]=mi[i-1]*2;for(int i=1;mi[i]<=maxd+1;++i) for(int j=1;j<=n;++j) fa[j][i]=fa[fa[j][i-1]][i-1];m=read();for(int qaq=1;qaq<=m;++qaq) {x=read();for(int i=1;i<=x;++i) node[i]=read(),vis[node[i]]=1;sort(node+1,node+x+1,cmp);xx=x;//for(int i=2;i<=xx;++i) {z=getlca(node[i-1],node[i]);if(!vis[z]) node[++x]=z,vis[z]=2;}if(!vis[1]) node[++x]=1,vis[1]=2;sort(node+1,node+x+1,cmp);y=1;zz[1]=node[1];dp[node[1]]=0;for(int i=2;i<=x;++i) {dp[node[i]]=len[node[i]];while(y&&id[node[i]]>end[zz[y]]) y--;fath[node[i]]=zz[y];dp[zz[y]]=0;zz[++y]=node[i];//}for(int i=x;i>1;i--) {if(vis[node[i]]==2) dp[node[i]]=min(dp[node[i]],len[node[i]]);//else dp[node[i]]=len[node[i]];dp[fath[node[i]]]+=dp[node[i]];}printf("%lld\n",dp[node[1]]);for(int i=1;i<=x;++i) vis[node[i]]=0;}return 0;
}

数据结构入门9—虚树相关推荐

  1. 数据结构专题——虚树

    虚树(virtual tree)的概念 虚树 是将一个树的点集的某一个子集,以及该子集中点的 LCALCALCA 的集合,一起所重构出来的一棵树 虚树的用途 在树型dp中,有时候没必要对整颗树进行dp ...

  2. P2495 [SDOI2011]消耗战 虚树入门

    一棵树,n个点m个操作.每条边有权值,每个操作给你k个点,问断开若干条边后使k个点与根不相连的最小边权和是多少. 有sigmaK<500000 易知一个裸的树dp需要复杂度,m次操作后总复杂度为 ...

  3. 数据结构入门(一级)

    数据结构和算法的入门:在这里我们先回答大家三个问题1. 为什么要学习数据结构2. 有哪些数据结构3. 学习数据结构的四种境界知道了这三个问题之后呢,再来进行具体内容的一个学习,先看第一个,为什么要学些 ...

  4. 牛客多校1 - Infinite Tree(虚树+换根dp+树状数组)

    题目链接:点击查看 题目大意:给出一个无穷个节点的树,对于每个大于 1 的点 i 来说,可以向点 i / minvid[ i ] 连边,这里的 mindiv[ x ] 表示的是 x 的最小质因数,现在 ...

  5. 浅谈虚树(虚仙人掌)

    虚树是什么? 在 OI 比赛中,有这样一类题目:给定一棵树,另有多次询问,每个询问给定一些关键点,需要求这些关键点之间的某些信息.询问数可能很多,但满足所有询问中关键点数量的总和比较小. 由于询问数可 ...

  6. Java数据结构(1.1):数据结构入门+线性表、算法时间复杂度与空间复杂度、线性表、顺序表、单双链表实现、Java线性表、栈、队列、Java栈与队列。

    数据结构与算法入门 问题1:为什么要学习数据结构          如果说学习语文的最终目的是写小说的话,那么能不能在识字.组词.造句后就直接写小说了,肯定是不行的, 中间还有一个必经的阶段:就是写作 ...

  7. 《LeetCode》数据结构入门板块

    文章目录 <LeetCode题>数据结构入门板块 第1天 数组 217.存在重复元素[简单,哈希表] 53.最大子序和[简单,动态规划,贪心] 第2天 数组 1.两数之和[简单,哈希表] ...

  8. 数据结构入门(8) ——查找

    数据结构入门 --查找 文章目录 数据结构入门 --查找 前言 一.线性表查找 顺序查找 有序表的二分查找 对半(折半)查找 二叉判定树 对半查找总结 一致对半查找 斐波那契查找 插值查找 二.查找树 ...

  9. 洛谷P2495 [SDOI2011]消耗战(虚树dp)

    P2495 [SDOI2011]消耗战 题目链接 题解: 虚树\(dp\)入门题吧.虚树的核心思想其实就是每次只保留关键点,因为关键点的dfs序的相对大小顺序和原来的树中结点dfs序的相对大小顺序都是 ...

最新文章

  1. [JDK8]性能优化之使用LongAdder替换AtomicLong
  2. Unity3D粒子系统碰撞器抑制、反弹
  3. Ajax Get请求获取后台返回的数据
  4. JAVA类 与类文件
  5. 2.1.3码元、波特、速率、带宽
  6. din算法 代码_从啥也不会的小白,如何成为合格的算法工程师?
  7. 2018年小米竟发布了16款手机,然而最值得入手的是它!
  8. 西瓜书+实战+吴恩达机器学习(六)监督学习之逻辑回归 Logistic Regression
  9. Eclipse中如何让Java类与Servlet产生关联【实现处理请求内容】
  10. 炼数成金数据分析课程---10、python中如何画图
  11. 【机器学习】GBDT+LR算法进行特征扩增
  12. c++ 写并查集算法模板
  13. 新浪微博注册页面的用户体验分析报告(转载)
  14. java泊松分布随机数,C语言生成泊松分布随机数
  15. 混沌理论作业简析——两人一组_图像加密解密小游戏
  16. 如何删除电脑计算机用户名和密码,如何删除电脑设置的密码
  17. windows 鼠标突然变成锯齿状
  18. 计算机音乐谱子 追光者,岑宁儿《追光者》简谱
  19. 如何查看手机、电脑设备配置?快来了解下你的电脑和手机吧~ 解读系统配置-cmd的简单应用
  20. KSO-Linux下Centos7.5防火墙开放某个端口号权限

热门文章

  1. java 指针定义_Java中关于指针的个人理解
  2. 很好的例子理解区别 Maximum Likelihood (ML) Maximum a posteriori (MAP)
  3. java使用jsoup爬虫入门
  4. C语言数据结构一元多项式
  5. APEX包管理器简述(二)
  6. TLE两行数与轨道六根数转换
  7. 二元函数对xy同时求导_更新丨10分钟掌握高等数学上册函数极限求解问题(考研、期末复习均可以用)...
  8. Python读取图片中的文字(OCR)
  9. 抢占1000万辆级别市场风口,这家国产Tier 1定点车型已超20款
  10. Deep Anomaly Detection with Deviation Networks 论文笔记