做法:求出树的直径,对两个端点做哈希。
#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 = 1;
for (auto v : G[u])
if (v != fa)
res = (res + dfs3(v, u, mod) * pr[siz[v]] % mod) % mod;
return res;
}
void hsh(long long &h1, long long &h2, int d1, int d2){
memset(siz, 0, sizeof siz);
dfs2(h1, 0);
h1 = (dfs3(d1, 0, mod1) + dfs3(d2, 0, mod1)) % mod1;
dfs2(h2, 0);
h2 = (dfs3(d1, 0, mod2) + dfs3(d2, 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);
}
memset(f, 0, sizeof f);
fst = rt;
dfs(rt, 0, 0);
int d1 = fst, d2;
memset(f, 0, sizeof f);
fst = d1;
dfs(d1, 0, 0);
d2 = fst;
hsh(hsh1, hsh2, d1, d2);
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";
}
}