题意:
给定一棵树,割掉某个点后树能分成 x x x个相同的子树,求最大的 x x x.
思路:
答案节点很容易发现就是树的重心。因此只要判断重心的子树是否同构就行了。
我的方法是处理出重心的子节点的hash值,n方暴力判断每个节点的hash值。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 4e3+5;
const int mod = 998244353;
int n;
vector<int>g[maxn];
vector<ll>s[maxn];
ll h[maxn],q[maxn],gg[maxn];
int prime[1000005],top = 0,v[maxn],p[1000005],siz[maxn],vis[1000005];
void getp(int m){
for(int i = 2; i <= m; i++){
if(!vis[i]){
p[++top] = i;
}
for(int j = 1; j <= top && i*p[j] <= m; j++){
vis[i*p[j]] = 1;
if(i%p[j] == 0) break;
}
}
}
void dfs1(int u,int fa){
siz[u] = 1;
h[u] = 1;
for(auto v:g[u]){
if(v == fa) continue;
dfs1(v,u);
h[u] = (h[u] + 1ll*h[v]*p[siz[v]]%mod)%mod;
siz[u] += siz[v];
}
return ;
}
int sz[maxn],f[maxn],G;
void getG(int u,int fa){
sz[u] = 1, f[u] = 0;
for(auto v:g[u]){
if(v == fa) continue;
getG(v,u);
sz[u] += sz[v];
f[u] = max(f[u],sz[v]);
}
f[u] = max(f[u],n-sz[u]);
if(f[u] < f[G]) G = u;
}
void dfs3(int u,int fa,int rt){
s[rt].push_back(h[u]);
for(auto v:g[u]){
if(v == fa) continue;
dfs3(v,u,rt);
}
}
bool check(int u,int v){
int len = s[u].size();
if(len != s[v].size()) return false;
for(int i = 0; i < len; i++){
if(s[u][i] != s[v][i]) return false;
}
return true;
}
int main(){
scanf("%d",&n);
getp(1000000);
for(int i = 1; i < n; i++){
int u,v;
scanf("%d%d",&u,&v);
g[u].push_back(v);
g[v].push_back(u);
}
f[0] = 1e6;
getG(1,0);
dfs1(G,0);
int ok = 1;
ll Hash;
for(int i = 0; i < g[G].size(); i++){
int v = g[G][i];
dfs1(v,G);
dfs3(v,G,v);
sort(s[v].begin(),s[v].end());
}
for(int i = 0; i < g[G].size(); i++){
for(int j = i+1; j < g[G].size(); j++){
if(!check(g[G][i],g[G][j])){
ok = 0;
break;
}
}
if(!ok) break;
}
if(ok) printf("%d\n",g[G].size());
else puts("-1");
return 0;
}