题目链接:点击打开链接
题目大意:给出一棵n个节点的树。1节点是根。如今有1到n。n个数放到每一个节点上。要求每一个子树中数字是连续的,同一个父节点的节点数字是连续的。问有多少种。
假设对于一个节点u来说,假设子节点vi数目是sum,子节点是叶子节点的数目是num。假设sum-num>2那么不能被构造,假设sum-num==2,那么方案是dp[u] = ∏dp[vi]*(num!),假设小于2,那么方案是dp[u] = ∏dp[vi]*(num!)*2注意取余
#include <cstdio> #include <cstring> #include <algorithm> using namespace std ; #define maxn 100010 #define LL __int64 const int Mod = 1e9+7 ; struct node{ int v , next ; }edge[maxn<<1] ; int head[maxn] , cnt ; int leaf[maxn] , flag ; LL s[maxn] , dp[maxn] ; void add(int u,int v) { edge[cnt].v = v ; edge[cnt].next = head[u] ; head[u] = cnt++ ; } void dfs(int u,int fa) { int i , v , num = 0 , sum = 0 ; dp[u] = leaf[u] = 1 ; for(i = head[u] ; i != -1 ; i = edge[i].next) { v = edge[i].v ; if( v == fa ) continue ; leaf[u] = 0 ; dfs(v,u) ; dp[u] = dp[u]*dp[v]%Mod ; sum++ ; if( leaf[v] ) num++ ; } if( sum == 0 ) return ; if( sum-num > 2 ) flag = 1 ; if( sum-num == 2 ) dp[u] = dp[u]*s[num]%Mod ; else dp[u] = dp[u]*s[num]*2%Mod ; } int main() { int t , step = 0 ; int n , i , j , u , v ; s[0] = 1 ; for(i = 1 ; i <= 100000 ; i++) s[i] = s[i-1]*i%Mod ; scanf("%d", &t) ; while( t-- ) { scanf("%d", &n) ; memset(head,-1,sizeof(head)) ; cnt = 0 ; for(i = 1; i < n ; i++) { scanf("%d %d", &u, &v) ; add(u,v) ; add(v,u) ; } flag = 0 ; dfs(1,-1) ; if( flag ) dp[1] = 0 ; printf("Case #%d: %I64d ", ++step, dp[1]) ; } return 0 ; }