这题一看就可以二分
那么解决这题的关键就变成了怎么对树进行哈希,以及怎么快速维护哈希值
想了一个下午想了一个比较靠谱的哈希方法。
用一个p进制数(p>n且为质数)来表示每一个节点,这个数有depth位,depth位这个节点的深度,那么这个数在p进制下第i位表示这个点的depth-i的祖先是其父亲的第几个儿子。
大概长这样
子树中所有节点的哈希值之和作为这个子树的哈希值。
因为每个哈希值的组合表示了唯一一颗子树,那么出现哈希值重合但是不同构的子树的概率就很小了
在二分中检验的时候,dfs一遍,可以用按深度建可并堆来维护K-子树,每次合并子树的可并堆,并在子树可并堆上打个乘p+tag的标记,并且把深度超过二分的d时弹出堆,然后用map记一下哈希值就可以了。
轻松垫底
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <vector>
#include <map>
#include <string>
#include <cstring>
using namespace std;
const int N=100010,base=100003;
typedef unsigned long long ll;
int n,x,u,cnt;