如果我们确定了每个叶子之间的相对大小关系,就可以用贪心来解决这个问题了。
对于每一个祖先,它的编号一定大于它的所有儿子。
我们从大到小来枚举所有编号(这里指相对大小)。
令dp[i]表示i这个状态的节点可以得到的最大乘积。
有dp[i]可以转移到dp[i+j],其中j这个状态仅有一个节点,并且那个节点的权值是可以算出来的。
令f[i]表示i这个状态的节点全部向根染色后最终会有多少点被染色。
通过f数组就能求出权值了。
最大乘积可以通过对数转化为加法来判断,就可以避免高精度了。
时间复杂度为2^20*20。
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long ll;
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
if (p1==p2){ p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
return *p1++;
}
inline void read(int &x){
char c=nc(),b=1;
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}
const int N=100005;
const int K=21;
struct edge{
int u,v,next;
}G[N<<1];
int head[N],inum;
inline void add(int u,int v,int p){
G[p].u=u; G[p].v=v; G[p].next=head[u]; head[u]=p;
}
int fat[N][K],depth[N];
int size[N];
int tag[N];
#define V G[p].v
inline void dfs(int u,int fa){
tag[u]=1;
size[u]=1; fat[u][0]=fa; depth[u]=depth[fa]+1;
for (int k=1;k<K;k++) fat[u][k]=fat[fat[u][k-1]][k-1];
for (int p=head[u];p;p=G[p].next)
if (V!=fa)
dfs(V,u),size[u]+=size[V],tag[u]=0;
}
inline int LCA(int u,int v){
if (depth[u]<depth[v]) swap(u,v);
for (int k=K-1;~k;k--)
if ((depth[u]-depth[v])&(1<<k))
u=fat[u][k];
if (u==v) return u;
for (int k=K-1;~k;k--)
if (fat[u][k]!=fat[v][k])
u=fat[u][k],v=fat[v][k];
return fat[v][0];
}
int n;
int cnt,lst[K],bac[N];
int top[N],sta[N];
inline int find(int u,int fa,int z){
top[u]=z; int s=0;
if (tag[u]) z=u;
for (int p=head[u];p;p=G[p].next)
if (V!=fa)
s|=find(V,u,z);
if (tag[u]==1) s|=1<<(bac[u]-1);
sta[u]=s;
return s;
}
const ll P=1e9+7;
double val[1<<K];
int last[1<<K];
int Pre[1<<K];
double Log[N];
inline void Init(){
for (int i=1;i<=n;i++)
Log[i]=log(i);
}
int main(){
int ix,iy,pre,x,cot,k;
read(n);
for (int i=1;i<n;i++){
read(ix); read(iy); add(ix,iy,++inum); add(iy,ix,++inum);
}
dfs(1,0);
for (int i=1;i<=n;i++)
if (tag[i])
lst[++cnt]=i,bac[i]=cnt;
for (int i=1;i<=cnt;i++)
for (int j=1;j<=cnt;j++)
if (i!=j)
tag[LCA(lst[i],lst[j])]=2;
find(1,0,0);
last[0]=0;
Init();
for (int i=1;i<(1<<cnt);i++){
pre=0;
for (int j=1;j<=cnt;j++)
if (i>>(j-1)&1)
if (!pre || val[pre]+Log[last[pre]+1]<val[i-(1<<(j-1))]+Log[last[i-(1<<(j-1))]+1])
pre=i-(1<<(j-1)),k=j;
val[i]=val[pre]+Log[last[pre]+1];
Pre[i]=pre;
x=lst[k],cot=last[pre];
while (x!=0 && sta[x]==(i&sta[x])){
cot+=depth[x]-depth[top[x]];
x=top[x];
}
last[i]=cot;
}
ll ret=1; x=(1<<cnt)-1;
while (x){
ret*=last[Pre[x]]+1; ret%=P;
x=Pre[x];
}
printf("%I64d\n",ret);
return 0;
}