您的位置:首页 > 大数据 > 人工智能

2015 Multi-University Training Contest 7 hdu 5378 Leader in Tree Land

2015-08-19 14:07 495 查看

Leader in Tree Land

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


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 \leq n \leq 1000,1 \leq k \leq 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

Author
UESTC

Source
2015 Multi-University Training Contest 7 1010

解题:动态规划 这位博主大牛说得非常清楚

我们用x[i],y[i]分别代表这个节点能够成为leader和不能够成为leader的概率。

son[i] 代表以i节点为根的子树的节点数。

那么$x[i] = 1/son[i],y[i] = 1-(1/son[i])$。因为这里面出现了分数,所有我们用逆元处理一下。

我们设dp[i][j]表示编号为1,2...i的节点中有j个leader的概率。

那么转移方程就是 $dp[i][j] = dp[i-1][j-1] * x[i] + dp[i-1][j] * y[i]$。

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL mod = 1000000007;
const int maxn = 1010;
struct arc {
int to,next;
arc(int x = 0,int y = -1) {
to = x;
next = y;
}
} e[maxn<<1];
int son[maxn],head[maxn],tot;
LL F[maxn] = {1},x[maxn],y[maxn],dp[maxn][maxn];
void init() {
for(int i = 1; i < maxn; ++i)
F[i] = F[i-1]*i%mod;
}
void add(int u,int v) {
e[tot] = arc(v,head[u]);
head[u] = tot++;
}
LL gcd(LL a,LL b,LL &x,LL &y) { //ax + by = gcd(a,b)
if(!b) {
x = 1;
y = 0;
return a;
}
LL ret = gcd(b,a%b,y,x);
y -= x*(a/b);
return ret;
}
LL Inv(LL b,LL mod) { //求b % mod的逆元
LL x,y,d = gcd(b,mod,x,y);
return d == 1?(x%mod + mod)%mod:-1;
}
void dfs(int u,int fa) {
son[u] = 1;
for(int i = head[u]; ~i; i = e[i].next) {
if(e[i].to == fa) continue;
dfs(e[i].to,u);
son[u] += son[e[i].to];
}
}
int main() {
int kase,n,k,u,v,cs = 1;
init();
scanf("%d",&kase);
while(kase--) {
scanf("%d%d",&n,&k);
memset(head,-1,sizeof head);
tot = 0;
for(int i = 1; i < n; ++i) {
scanf("%d%d",&u,&v);
add(u,v);
add(v,u);
}
dfs(1,-1);
for(int i = 1; i <= n; ++i) {
x[i] = Inv(son[i],mod);
y[i] = (son[i] - 1)*x[i]%mod;
}
memset(dp,0,sizeof dp);
dp[1][0] = y[1];
dp[1][1] = x[1];
for(int i = 2; i <= n; ++i) {
dp[i][0] = dp[i-1][0]*y[i]%mod;
for(int j = 1; j <= min(i,k); ++j) {
LL a = dp[i-1][j-1]*x[i]%mod;
LL b = dp[i-1][j]*y[i]%mod;
dp[i][j] = (a + b)%mod;
}
}
printf("Case #%d: %I64d\n",cs++,dp
[k]*F
%mod);
}
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: