对于无标号树计数首先要找到其重心作根,如果有多个就再建一个点连着两个点;这样能够保证一个节点的某棵子树不会和整棵树减去当前这颗子树形成的树同构,这样就转化为有根树。哈希就随便哈希即可。这个题,如果一个节点有x颗同构的树并且每一颗子树都有y中方案,那么就相当于y个变量每个变量取值>=0其和为x的方案数,组合数一波即可。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define uint unsigned long long int
#define lint long long
#define N 500010
#define mod 1000000007
#define gc getchar()
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
using namespace std;
int n,sz[N],zx[3],fac[N],facinv[N];uint hv[N];
inline bool hash_cmp(int x,int y) { return hv[x]<hv[y]; }
inline int fast_pow(int x,int k,int ans=1)
{ for(;k;k>>=1,x=(lint)x*x%mod) (k&1)?ans=(lint)ans*x%mod:0;return ans; }
inline int prelude(int n)
{
for(int i=fac[0]=1;i<=n;i++) fac[i]=(lint)fac[i-1]*i%mod;
facinv[n]=fast_pow(fac[n],mod-2);
for(int i=n-1;i>=0;i--) facinv[i]=(lint)facinv[i+1]*(i+1)%mod;
return 0;
}
inline int C(int n,int m)
{
int ans=1;
for(int i=1;i<=m;i++)
ans=(lint)ans*(n-i+1)%mod;
return (lint)ans*facinv[m]%mod;
}
struct edges{
int to,pre;
}e[N<<1];int h[N],etop,tmp[N];
inline int add_edge(int u,int v)
{ return e[++etop].pre=h[u],e[etop].to=v,h[u]=etop; }
int dfs(int x,int fa)
{
sz[x]=1;
for(int i=h[x],y;i;i=e[i].pre)
if((y=e[i].to)^fa) tmp[x]=max(tmp[x],dfs(y,x)),sz[x]+=sz[y];
tmp[x]=max(tmp[x],n-sz[x]);
if(tmp[x]<tmp[zx[1]]) zx[1]=x,zx[2]=0;
else if(tmp[x]==tmp[zx[1]]) zx[2]=x;
return sz[x];
}
int son[N],f[N][2];
int getdp(int x,int fa)
{
for(int i=h[x],y;i;i=e[i].pre)
if((y=e[i].to)^fa) getdp(y,x);
int c=0;for(int i=h[x],y;i;i=e[i].pre)
if((y=e[i].to)^fa) son[++c]=y;
sort(son+1,son+c+1,hash_cmp),f[x][0]=f[x][1]=1;
for(int i=1,j,cnt,y;i<=c;i=j+1)
{
for(cnt=1,j=i;j<c&&hv[son[j+1]]==hv[son[i]];j++,cnt++);
y=son[i],f[x][1]=(lint)f[x][1]*C(cnt+f[y][0]-1,cnt)%mod,
f[x][0]=(lint)f[x][0]*C(cnt+f[y][0]+f[y][1]-1,cnt)%mod;
}
hv[x]=998244353;
for(int i=1;i<=c;i++) (((hv[x]*=hv[son[i]])^=hv[son[i]])+=hv[son[i]]);
return 0;
}
inline int inn()
{
int x,ch;while((ch=gc)<'0'||ch>'9');
x=ch^'0';while((ch=gc)>='0'&&ch<='9')
x=(x<<1)+(x<<3)+(ch^'0');return x;
}
int main()
{
n=inn();
for(int i=1,u,v;i<n;i++)
u=inn(),v=inn(),add_edge(u,v),add_edge(v,u);
tmp[zx[1]]=n+1,prelude(n+1),dfs(1,0);int rt=0;
if(!zx[2]) rt=zx[1];
else{
rt=n+1;
for(int i=h[zx[1]];i;i=e[i].pre)
if(e[i].to==zx[2]) e[i].to=e[((i-1)^1)+1].to=rt;
add_edge(rt,zx[1]),add_edge(rt,zx[2]);
}
getdp(rt,0);int ans=0;
if(!zx[2]) ans=(f[zx[1]][0]+f[zx[1]][1])%mod;
else{
int x=zx[1],y=zx[2];if(hv[x]==hv[y]) ans=(((lint)f[x][0]*f[y][1]%mod+C(f[x][0]+1,2))%mod)%mod;
else ans=(((lint)f[x][0]*f[y][1]%mod+(lint)f[x][1]*f[y][0]%mod)+(lint)f[x][0]*f[y][0]%mod)%mod;
}
return !printf("%d\n",ans);
}