虚树学习笔记?
-
虚树是一棵虚拟构建的树…
废话这棵树只包含关键点和关键的点,而其他不影响虚树结构的点和边都相当于进行了路径压缩…而且整棵虚树的大小不会超过关键点的2倍- 举个例子?
- 比方说…
4
5
6
7
表示关键点(现在你要让这些关键点也形成一棵树…要求点最少但不能破坏原来树的结构) - 构建完的虚树长这个样(其实这也是构建虚树时候的最坏情况…所有原来树上的点都加入了虚树之中)
- 什么时候才会出现这种最坏的情况???当所有叶子节点都是关键点的时候…,但是很显然的是叶子结点不会超过 n 2 \dfrac{n}{2} 2n个
-
如何构建虚树?
-
预处理出dfs序…将关键点按照dfs序进行排序
-
我们使用一个栈,从栈顶到栈底的元素形成虚树的一条树链.
-
Code
-
sort(af + 1, af + 1 + num, cmp); if(con[1] != 1) st[++top] = 1; for(int i = 1; i <= num; ++i) { int pos = af[i], fa = 0; for(; top;) { fa = GetLCA(st[top], pos); if(top > 1 && dep[fa] < dep[st[top - 1]]) { add(st[top - 1], st[top]), top--; } else if(dep[fa] < dep[st[top]]) { add(fa, st[top]), top--; break; } else { break; } } if(st[top] != fa) st[++top] = fa; st[++top] = pos; } for(; top > 1; --top) add(st[top - 1], st[top]);
-
-
-
正确性✅?
- 对于任意指定两点 a , b a,b a,b 的 l c a lca lca ,都存在 d f s dfs dfs 序连续的两点 u , v u,v u,v( d f n [ u ] ≤ d f n [ v ] dfn[u]\leq dfn[v] dfn[u]≤dfn[v]) 分别属于 l c a lca lca包含 a , b a,b a,b 的两棵子树,此时这 v v v 加入时按照上面的操作必定会把 l c a lca lca加入栈,所以应当加入的点都加入了。对于非 l c a lca lca 点,按照上面操作是不会出现这个点的。
HDU6035 Colorful tree
-
题意:
- 给你一棵 n ( 1 ≤ n ≤ 200000 ) n(1\leq n\leq 200000) n(1≤n≤200000)个节点的树…每一个节点有一个颜色.一条路径的权值定义为出现颜色集合的大小…问所有路径的权值和是多少…
-
题解:
当我们在考虑这个问题怎么求的时候…我们很容易地考虑到要计算每个颜色的贡献
我们会发现这样正着做会很难…遇难则反
- 问题转换为求有多少条路径没有出现过颜色 c c c
事实上我们并不需要构建出每一种颜色的虚树… 只需一遍dfs就可以考虑啦!
但是应用到了虚树的思想…
首先一个颜色没有 c o l col col的联通块里任意两个点的路径上都不会出现 c o l col col这个颜色
我们记录一个 s u m [ x ] sum[x] sum[x]表示遍历到当前这个点 颜色为 x x