HDOJ 5378 Leader in Tree Land 概率DP


方法太屌,只能看一看了.....


可以用求概率的思想来解决这个问题。令以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!乘上概率就是答案。计算的时候用逆元代替上面的分数即可。


Leader in Tree Land

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


Problem Description
Tree land has  n  cities, connected by  n1  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  n1  line describe the roads of tree land.

T=10,1n1000,1kn
 

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
 

Source
 



/* ***********************************************
Author        :CKboss
Created Time  :2015年08月13日 星期四 10时59分40秒
File Name     :HDOJ5378.cpp
************************************************ */

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <cmath>
#include <cstdlib>
#include <vector>
#include <queue>
#include <set>
#include <map>

using namespace std;

typedef long long int LL;

const int maxn=1100;
const LL mod=1000000007LL;

int n,k;
LL dp[maxn][maxn],sz[maxn];
vector<int> G[maxn];

void clear()
{
	for(int i=0;i<=n+10;i++) G[i].clear();
}

LL dfs(int u,int fa)
{
	sz[u]=1LL;
	for(int i=0,ss=G[u].size();i<ss;i++)
	{
		int v=G[u][i];
		if(v==fa) continue;
		sz[u]+=dfs(v,u);
	}
	return sz[u];
}


LL inv[2*maxn],jc[2*maxn];

void init()
{
	jc[0]=1; inv[1]=1;jc[1]=1;
	for(LL i=2;i<2*maxn;i++)
	{
		inv[i]=(inv[mod%i]*(mod-mod/i))%mod;
		jc[i]=(jc[i-1]*i)%mod;
	}
}

int main()
{
	//freopen("in.txt","r",stdin);
	//freopen("out.txt","w",stdout);

	init();
	int T_T,cas=1;
	scanf("%d",&T_T);
	while(T_T--)
	{
		scanf("%d%d",&n,&k);
		clear();
		for(int i=0,u,v;i<n-1;i++)
		{
			scanf("%d%d",&u,&v);
			G[u].push_back(v);
			G[v].push_back(u);
		}
		dfs(1,1);
		dp[0][0]=1LL;
		for(int i=1;i<=n;i++)
		{
			for(int j=0;j<=i;j++)
			{
				dp[i][j]=((dp[i-1][j]*(sz[i]-1))%mod*inv[sz[i]])%mod;
				if(j) dp[i][j]=(dp[i][j]+(dp[i-1][j-1]*inv[sz[i]])%mod)%mod;
			}
		}

		LL ans=(dp[n][k]*jc[n])%mod;
		cout<<"Case #"<<cas++<<": "<<ans<<endl;
	}
    
    return 0;
}



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值