题意是把1--n放到一个节点数为n的树上,满足一个节点的儿子节点的值是连续的,任何一个子树内的值的连续的
首先对于任何一个子树来说,根节点一定在最旁边(假如在两个子节点中间,破坏了第一个规定),然后,一个根节点的儿子中,最多只有两个儿子可以有自己的儿子(不然无法同时满两个条件)。
最后dfs再排列组合一下就好了
#pragma comment(linker, "/STACK:102400000,102400000")
#include <iostream>
#include<stdio.h>
#include<string.h>
#include<vector>
#include<algorithm>
#include<cmath>
#include<map>
#include<set>
#include<queue>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1 | 1
#define lowbit(x) x&(-x)
using namespace std;
const int N=1e5+10;
long long inf=1e15;
const int MOD=1e9+7;
int T,n,m,k,x,y,z,l,tot,t;
int cas=1;
int son[N];
bool ok;
vector<int> G[N];
long long A[N];
long long dp[N];/*dp[i] 表示以i为根,且根在子树中排在最左边的分配数目*/
void dfs(int x,int fa){
son[x]=1;
int num=0;/*所有儿子数*/
int cnt=0;/*有自己的儿子的儿子数*/
long long res=1;
for(int i=0;i<G[x].size();i++){
int u=G[x][i];
if(u==fa) continue;
num++;
dfs(u,x);
son[x]+=son[u];
if(son[u]>1){
cnt++;
res=(res*dp[u])%MOD;
}
}
if(cnt>2){
ok=true;
return;
}else if(cnt==2 || cnt==1){/*两个大儿子中间夹着一排叶子儿子 或者 一个大儿子旁边一排叶子儿子,大儿子可以左右换一下,所以*2 */
res=(res*2*A[num-cnt])%MOD;
}else if(cnt==0){/*儿子全是叶子节点*/
res=(res*A[num-cnt])%MOD;
}
dp[x]=res;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("aaa","r",stdin);
#endif
int T;
A[0]=1;
for(int i=1;i<N;i++) A[i]=(A[i-1]*i)%MOD;
scanf("%d",&T);
while(T--){
scanf("%d",&n);
for(int i=1;i<=n;i++) G[i].clear();
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);
}
ok=false;
dfs(1,-1);
long long ans=(dp[1]*2)%MOD;/*根分到最小值和最大值两种情况*/
if(ok) ans=0;/*不可能的情况*/
if(n==1) ans=1;/*n=1的情况另外考虑*/
printf("Case #%d: %I64d\n",cas++,ans);
}
return 0;
}