这道题一直re,结果是忘了手动扩栈了,好伤~~~~~ 以后要切记
题意:有n个人呈树状结构,每个人知道一个独特的消息。每次可以让一个人将他所知的所有消息告诉和他相邻的人。求所有人都知道所有消息花时花的步 数最少的所有方案数。
思路:以每个节点作为信息汇总点,先把信息都传到这个点,再由这个点扩展开去。
首先建树,然后从根节点出发,计算每个儿子节点的儿子数量a1,a2,a3...........an,总儿子个数为sum,根据顺序的不同可得,
共有C(sum,a1)*C(sum-a1,a2)*(sum-a1-a2,a3)*...........*(an-1+an-2,an-1)*(an,an),这么多种走法。
与此同时,它的每棵子树里面若有分支,则它本身也有不同的走法,所以继续对子树1,子树2...........继续按以上方法计算,累乘。
因为信息汇总后还需要扩展,求得的积需要再平方。
接下来就以他的子树作为汇总点计算有集中走法,这时候子节点的总数可以利用上一步父亲节点求得的结果来计算。
最终算出所有的走法总数。
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<string.h>
#define LL long long
const int mod=1000000000+7;
const int maxn=1111111;
struct node
{
int son;
LL sum;
}f[maxn];
LL fact[maxn],ans;
int head[maxn],nxt[2*maxn],u[2*maxn],e,n;
bool vis[maxn];
void getfact()
{
LL i;
fact[0]=1;
for(i=1;i<=maxn;i++)
fact[i]=fact[i-1]*i%mod;
}
void init(int n)
{
int i,j;
e=0;
for(i=1;i<=n;i++)head[i]=-1;
}
void addedge(int x,int y)
{
u[e]=y;
nxt[e]=head[x];
head[x]=e++;
}
LL modstyle(LL s)
{
if(s>=mod)s%=mod;
if(s<0)s=s%mod+mod;
return s;
}
void extEuclid(LL a,LL b,LL &x,LL &y)
{
if(b==0){x=1;y=0;return ;}
extEuclid(b,a%b,x,y);
LL tmp=x;x=y;y=tmp-a/b*y;
}
node buildtree(int s)
{
int i,j;
vis[s]=1;
LL x,y,sum=1;
int son=0;
node p;
for(i=head[s];i!=-1;i=nxt[i])
{
if(vis[u[i]])continue;
p=buildtree(u[i]);
son+=p.son;
sum=sum*p.sum%mod;
extEuclid(fact[ p.son ]*fact[ son-p.son ]%mod,mod,x,y);
x=modstyle(x);
sum=sum*fact[ son ]%mod*x%mod;
}
f[s].son=son+1;
f[s].sum=sum;
return f[s];
}
void solve(int s,LL presum)
{
int i,j,k,son=f[s].son;
LL x,y,sum=f[s].sum,a,b;
LL cursum;
if(presum==-1){
cursum=sum;
ans+=sum*sum%mod;
}
else
{
a=fact[n-1-son]*fact[son]%mod;
extEuclid(fact[n-1-(son-1)]*fact[son-1]%mod,mod,x,y);
b=modstyle(x);
cursum=presum*a%mod*b%mod;
ans+=cursum*cursum%mod;
}
vis[s]=1;
for(i=head[s];i!=-1;i=nxt[i])
{
if(vis[u[i]])continue;
solve(u[i],cursum);
}
}
int main()
{
int i,j,t,k,x,y;
getfact();
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
init(n);
for(i=1;i<n;i++)
{
scanf("%d%d",&x,&y);
addedge(x,y);
addedge(y,x);
}
for(i=1;i<=n;i++)vis[i]=0;
buildtree(1);
for(i=1;i<=n;i++)vis[i]=0;
ans=0;
solve(1,-1);
printf("%I64d\n",ans%mod);
}
return 0;
}