P4128[Jsoi2016]独特的树叶
问题描述
JYY有两棵树A和B:树A有N个点,编号为1到N;树B有N+1个点,编号为1到N+1。JYY知道树B恰好是由树A加上一个叶
节点,然后将节点的编号打乱后得到的。他想知道,这个多余的叶子到底是树B中的哪一个叶节点呢?
输入格式
输入一行包含一个正整数N。
接下来N-1行,描述树A,每行包含两个整数表示树A中的一条边;
接下来N行,描述树B,每行包含两个整数表示树B中的一条边。
1≤N≤10^5
输出格式
输出一行一个整数,表示树B中相比树A多余的那个叶子的编号。如果有多个符合要求的叶子,输出B中编号最小的那一个的编号。
样例输入
5
1 2
2 3
1 4
1 5
1 2
2 3
3 4
4 5
3 6
样例输出
1
这道题用树哈希来处理比较方便。
先将树A以每个点作为根的哈希值都算出来存到一个set中,然后将树B去掉一个叶子节点后算出哈希值,再在set中查找。
如果直接算n次哈希会超时,需要用到递推求哈希值。
这里为了方便递推,我用的哈希函数是
$父节点Hash=(Hash[son_1]+p)\bigoplus (Hash[son_2]+p)\bigoplus……+size*q+1$
那么递推的方式就比较显然了,具体可以参见代码。
只需要做一次树dp就可以求出以每个点为根的哈希值。
至于树B去掉一个叶子后的哈希值,事实上也可以同样的递推,只需要在处理到叶子节点的父节点时算一下以他为根,且去掉这个叶子的哈希值然后在set中查找即可。
用unordered_set可以做到近似$O(n)$
代码:
1 |
|