Leader in Tree Land(概率dp+求逆元+树)

Leader in Tree Land

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

Problem Description

Tree land has n cities, connected by n−1 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 n ministers numbered from 1 to n. You will send them to n cities, one city with one minister.

Since this is a rooted tree, each city is a root of a subtree and there are n 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 k ministers. You want to know how many ways to send n ministers to each city so that there are k ministers attend the meet.

Give your answer mod 1000000007.

Input

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

T=10,1≤n≤1000,1≤kn

Output

For each test case, output one line. The output format is Case #x: ans, x is the case number,starting from 1.

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

Author

UESTC

Source

2015 Multi-University Training Contest 7

Recommend

wange2014   |   We have carefully selected several similar problems for you:  6361 6360 6359 6358 6357 

这道题可以用概率dp做。

思路:

(由于没有用longlong,没有初始化tot,导致一直WA)

感觉这道题非常好!!!给图的作用就是求当前点为根点,在子树中是否为leader的概率

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=1010;
#define mod 1000000007

int T,k,cas,tot;
int head[maxn*2];
ll siz[maxn];///以u为根节点的子树个数
ll inv[maxn];
ll dp[maxn][maxn];
struct node{
    int v,next;
}edge[maxn*2];

void add(int a,int b){
    edge[++tot].v=b;
    edge[tot].next=head[a];
    head[a]=tot;
}
void dfs(int v,int f)
{
    siz[v]=1;
    for(int i=head[v];i;i=edge[i].next)
    {
        if (edge[i].v!=f)
        {
            dfs(edge[i].v,v);
            siz[v]+=siz[edge[i].v];
        }
    }
}
void dfs1(int u,int fa){
    siz[u]=1;
    for(int i=head[u];i;i=edge[i].next){
        if(edge[i].v!=fa){
           dfs(edge[i].v,u);
           siz[u]+=siz[edge[i].v];
        }
    }
}

ll power(ll a,ll b)
{
    ll ans=1,s=a;
    while(b)
    {
        if (b&1)
            ans=(ans*s)%mod;
        b>>=1;
        s=(s*s)%mod;
    }
    return ans;
}

int main()
{
    int u,v,n,k;
    cas=0;
    for(int i=1;i<=1001;i++){
        inv[i]=power((ll)i,mod-2);
    }
    scanf("%d",&T);
    while(T--){
            tot=0;
        memset(head,0,sizeof(head));
        memset(dp,0,sizeof(dp));
        cas++;
        scanf("%d%d",&n,&k);
        for(int i=1;i<n;i++)
        {
            scanf("%d%d",&u,&v);
            add(u,v);add(v,u);
        }
        dfs(1,0);
        dp[0][0]=1;
        for(int i=1;i<=n;i++){
            for(int j=0;j<=i;j++){
                dp[i][j]=(((dp[i-1][j]*(siz[i]-1))%mod)*inv[siz[i]])%mod;
                dp[i][j]=(dp[i][j]+dp[i-1][j-1]*inv[siz[i]])%mod;
            }
        }
       for(int i=1;i<=n;i++)
            dp[n][k]=(dp[n][k]*i)%mod;
        printf("Case #%d: %lld\n",cas,dp[n][k]);
    }
}

/*
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
*/

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值