rt,本题按照如下方法哈希可过:
选取一棵树的每个点为根,搜出所有点的深度和子树大小,然后暴力哈希。
具体见下面一个 AC 的暴力代码:
#include<bits/stdc++.h>
using namespace std;
const int mod1 = 998244353, mod2 = 998244352;
int t, n, rt, fst, f[55], siz[55];
vector<int> G[55];
struct node{
long long h1, h2;
bool operator < (node b)const{
return this->h1 < b.h1;
}
};
long long h1[55], h2[55];
int pr[105], cnt;
bool vis[105];
void sieve(int lim){
for (int i = 2; i <= lim; i++){
if (!vis[i]){
pr[++cnt] = i;
vis[i] = 1;
}
for (int j = 1; j <= cnt; j++){
if (i * pr[j] > lim)
break;
vis[i * pr[j]] = 1;
if (i % pr[j] == 0)
break;
}
}
}
void dfs(int u, int fa, int dep){
f[u] = dep;
if (dep > f[fst])
fst = u;
for (auto v : G[u]){
if (v == fa)
continue;
dfs(v, u, dep + 1);
}
}
void dfs2(int u, int fa){
for (auto v : G[u])
if (v != fa){
dfs2(v, u);
siz[u] += siz[v];
}
siz[u]++;
}
long long dfs3(int u, int fa, const int mod){
long long res = f[u];
for (auto v : G[u])
if (v != fa)
res = (res + dfs3(v, u, mod) * pr[siz[v]] % mod * pr[f[v]] % mod) % mod;
return res;
}
void hsh(long long &h1, long long &h2){
for (int i = 1; i <= n; i++){
memset(siz, 0, sizeof siz);
memset(f, 0, sizeof siz);
dfs(i, 0, 0);
dfs2(i, 0);
h1 = (h1 + dfs3(i, 0, mod1)) % mod1;
h2 = (h2 + dfs3(i, 0, mod2)) % mod2;
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
sieve(100);
cin >> t;
for (int iii = 1; iii <= t; iii++){
cin >> n;
for (int i = 1; i <= n; i++)
G[i].clear();
long long hsh1 = n, hsh2 = n;
for (int i = 1; i <= n; i++){
int fa;
cin >> fa;
if (!fa){
rt = i;
continue;
}
G[fa].push_back(i);
G[i].push_back(fa);
}
hsh(hsh1, hsh2);
if (hsh1 < hsh2)
swap(hsh1, hsh2);
h1[iii] = hsh1;
h2[iii] = hsh2;
// cout << d1 << " " << d2 << " " << hsh1 << " " << hsh2 << "\n";
int fd = iii;
for (int j = iii - 1; j; j--)
if (h1[j] == h1[iii] && h2[j] == h2[iii])
fd = j;
cout << fd << "\n";
}
}