HDU 5378 Leader in Tree Land(2015 多校第7场 dp)

Leader in Tree Land

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 150    Accepted Submission(s): 54


Problem Description
Tree land has   cities, connected by   roads. You can go to any city from any city. In other words, this land is a tree. The city numbered one is the root of this tree.

There are   ministers numbered from   to  . You will send them to   cities, one city with one minister. 

Since this is a rooted tree, each city is a root of a subtree and there are   subtrees. The leader of a subtree is the minister with maximal number in this subtree. As you can see, one minister can be the leader of several subtrees. 

One day all the leaders attend a meet, you find that there are exactly   ministers. You want to know how many ways to send   ministers to each city so that there are   ministers attend the meet.

Give your answer mod  .
 

Input
Multiple test cases. In the first line there is an integer  , indicating the number of test cases. For each test case, first line contains two numbers  . Next   line describe the roads of tree land.


 

Output
For each test case, output one line. The output format is Case #  is the case number,starting from  .
 

Sample Input
  
  
2 3 2 1 2 1 3 10 8 2 1 3 2 4 1 5 3 6 1 7 3 8 7 9 7 10 6
 

Sample Output
  
  
Case #1: 4 Case #2: 316512
 

Source

解题思路:

可以用求概率的思想来解决这个问题。令以i号节点为根的子树为第i棵子树,设这颗子树恰好有sz[i]个点。那么第i个点是第i棵子树最大值的概率为1/sz[i],不是最大值的概率为(sz[i]-1)/sz[i]。现在可以求解恰好有k个最大值的概率。

令dp[i][j]表示考虑编号从1到i的点,其中恰好有j个点是其子树最大值的概率。 很容易得到如下转移方程:dp[i][j]=dp[i-1][j]*(sz[i]-1)/sz[i]+dp[i-1][j-1]/sz[i]。这样dp[n][k]就是所有点中恰好有k个最大值的概率。

题目要求的是方案数,用总数n!乘上概率就是答案。计算的时候用逆元代替上面的分数即可

#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#define LL long long
using namespace std;
const int MAXN = 1000 + 10;
const int MOD = 1000000000 + 7;
int read()
{
    int res = 0, f = 1; char ch = getchar();
    while(ch < '0' || ch > '9'){if(ch == '-') f *= -1; ch = getchar();}
    while(ch >= '0' && ch <= '9'){res = res * 10 + ch - '0'; ch = getchar();}
    return res;
}
int sz[MAXN], vis[MAXN];
int n, k;
LL dp[MAXN][MAXN], inv[MAXN], fac[MAXN];
struct Edge
{
    int to, next;
}edge[MAXN<<1];
int tot, head[MAXN];
void init()
{
    tot = 0;
    for(int i=0;i<=n;i++)
    {
        head[i] = -1;
        vis[i] = 0;
        sz[i] = 0;
    }
}
void addedge(int u, int v)
{
    edge[tot].to = v;
    edge[tot].next = head[u];
    head[u] = tot++;
}
int dfs(int u, int pre)
{
    int ans = 1;vis[u] = 1;
    for(int i=head[u];i!=-1;i=edge[i].next)
    {
        int v = edge[i].to;
        if(v == pre) continue;
        if(!vis[v]) ans += dfs(v, u);
    }
    return sz[u] = ans;
}
LL pow_mod(LL a, LL b)
{
    LL res = 1;
    while(b)
    {
        if(b & 1) res = res * a % MOD;
        a = a * a % MOD;
        b >>= 1;
    }
    return res % MOD;
}
int main()
{
    int T, kcase = 1;
    for(int i=1;i<MAXN;i++) inv[i] = pow_mod(i, MOD - 2);
    fac[0] = 1; for(int i=1;i<MAXN;i++) fac[i] = fac[i-1] * i % MOD;
    T = read();
    while(T--)
    {
        n = read(); k = read();
        int u, v; init();
        for(int i=1;i<n;i++)
        {
            u = read();v = read();
            addedge(u, v);
            addedge(v, u);
        }
        dfs(1, -1);
        for(int i=0;i<=n;i++) for(int j=0;j<=k;j++) dp[i][j] = 0;
        dp[0][0] = 1;
        for(int i=1;i<=n;i++)
        {
            for(int j=0;j<=k;j++)
            {
                dp[i][j] = ((dp[i-1][j] * (sz[i] - 1)) % MOD) * inv[sz[i]] % MOD +
                dp[i-1][j-1] * inv[sz[i]] % MOD;
            }
        }
        LL ans = (dp[n][k] * fac[n]) % MOD;
        printf("Case #%d: %I64d\n", kcase++, ans);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值