Leader in Tree Land
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 626 Accepted Submission(s): 283
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 .
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≤k≤n
T=10,1≤n≤1000,1≤k≤n
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
题意:1-n随机分配给每一个节点,子树的值表示为子树中的节点的最大值.问
所有的子树值有k种的方案数.
每一个节点为根的子树中自身为最大值的概率是1/size(i).然后用f[i][j]表示为
前i个节点中有j种最大值的概率,转移方程就很简单了.因为要避免浮点数,概率
用逆元来搞.
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <map>
#include <vector>
using namespace std;
#define maxn 1111
#define maxm maxn*2
#define mod 1000000007
struct node {
int v, next;
}edge[maxn];
int head[maxn], n, k, cnt;
long long dp[maxn];
long long rev[maxn];
long long f[maxn][maxn];
void add_edge (int u, int v) {
edge[cnt].v = v, edge[cnt].next = head[u], head[u] = cnt++;
}
void dfs (int u, int fa) {
dp[u] = 1;
for (int i = head[u]; i != -1; i = edge[i].next) {
int v = edge[i].v;
if (v == fa)
continue;
dfs (v, u);
dp[u] += dp[v];
}
}
long long cal (long long num) {
return (num%mod+mod)%mod;
}
long long solve () {
for (int i = 1; i <= n; i++) dp[i] = rev[dp[i]]%mod;
memset (f, 0, sizeof f);
f[1][1] = dp[1];
f[1][0] = cal (1-dp[1]);
for (int i = 2; i <= n; i++) {
for (int j = 0; j <= k; j++) {
f[i][j] += f[i-1][j]*cal (1-dp[i])%mod;
if (j)
f[i][j] += f[i-1][j-1]*dp[i]%mod;
f[i][j] %= mod;
}
}
long long ans = 1;
for (int i = 2; i <= n; i++)
ans *= i, ans %= mod;
return (ans*f[n][k] % mod);
}
void init() { //预处理逆元
rev[1] = 1;
for (int i = 2; i <= 1000; i++){
rev[i] = (long long)(mod - mod/i) * rev[mod % i] % mod;
}
}
int main () {
//freopen ("in.txt", "r", stdin);
init ();
int t, kase = 0;
cin >> t;
while (t--) {
cin >> n >> k;
memset (head, -1, sizeof head);
cnt = 0;
printf ("Case #%d: ", ++kase);
for (int i = 1; i < n; i++) {
int u, v;
scanf ("%d%d", &u, &v);
add_edge (u, v);
add_edge (v, u);
}
dfs (1, 0);
printf ("%lld\n", solve ());
}
return 0;
}