1. 程式人生 > >lightoj 1382 - The Queue(樹形dp)

lightoj 1382 - The Queue(樹形dp)

volume urn www. vector num clu href get 題目

題目鏈接:http://www.lightoj.com/volume_showproblem.php?problem=1382

題解:簡單的樹形dp加上組合數學。

#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#define mod 1000000007
using namespace std;
typedef long long ll;
const int M = 1234;
ll dp[M] , C[M][M];
int fa[M] , num[M];
vector
<int> vc[M]; void find_num(int u , int pre) { num[u] = 1; int len = vc[u].size(); for(int i = 0 ; i < len ; i++) { int v = vc[u][i]; if(v == pre) continue; find_num(v , u); num[u] += num[v]; } } void dfs(int u , int pre) { int len = vc[u].size(); ll ans
= 1 , sum = num[u]; for(int i = 0 ; i < len ; i++) { int v = vc[u][i]; if(v == pre) continue; dfs(v , u); ans *= (C[sum - 1][num[v]] * dp[v]) % mod; ans %= mod; sum -= num[v]; } dp[u] = ans; dp[u] %= mod; } int main() {
int t , n; int Case = 0; scanf("%d" , &t); C[0][0] = 1; for(int i = 1 ; i <= M - 1 ; i++) { C[i][0] = 1; for(int j = 1 ; j <= i ; j++) C[i][j] = (C[i - 1][j - 1] + C[i - 1][j]) % mod; } while(t--) { scanf("%d" , &n); for(int i = 1 ; i <= n ; i++) { vc[i].clear(); dp[i] = 1; fa[i] = -1; num[i] = 0; } for(int i = 0 ; i < n - 1 ; i++) { int u , v; scanf("%d%d" , &u , &v); vc[u].push_back(v); fa[v] = u; } int root = 1; for(int i = 1 ; i <= n ; i++) { if(fa[i] == -1) { root = i; break; } } find_num(root , -1); dfs(root , -1); printf("Case %d: %lld\n" , ++Case , dp[root] % mod); } return 0; }

lightoj 1382 - The Queue(樹形dp)