lightoj 1382 - The Queue(树形dp)

题目链接: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;
}

 

posted @ 2017-10-12 14:59  Gealo  阅读(242)  评论(0编辑  收藏  举报