HDU 5378 Leader in Tree Land 树形背包

链接

题解来源:点击打开链接

题意:

给定n k

下面n-1行给出一棵树。

把数字1-n填到树的节点上。

填完后计算leader节点个数,若这个点是leader,则这个点上填的数>这个点的子树上填的数

问:恰好有k个leader节点的 填涂方案数.

思路:

dp[i][j]表示以i点为根的子树 有恰好j个leader的方案数。

如果u 是叶子节点则 dp[u][0] = 0, dp[u][1] = 1;

如果u不是叶子节点:

先不考虑u点能否成为leader,背包一下。

然后考虑u点:若u能成为leader,设siz[u]表示u的子树节点个数。

那么对于u的子树来说,要把[1, siz[u] ]填到子树上,当u是leader, u只能填 siz[u]

而子树的分配方案就是一个多重集的排列,因为分配给子树的是组合,子树之间是排列。

设u成为leader的方法数为 x1

x1 = (siz[u]-1)! / siz[v1]! / siz[v2]! ····

那么dp[u][i] = dp[u][i] * (u的子树填涂的总方案数 - x1) + dp[u][i-1] * x1

#pragma comment(linker, "/STACK:102400000,102400000")
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
#include <cmath>
#include <cstring>
#include <queue>
#include <set>
#include <map>
#include <vector>
using namespace std;
template <class T>
inline bool rd(T &ret) {
	char c; int sgn;
	if (c = getchar(), c == EOF) return 0;
	while (c != '-' && (c<'0' || c>'9')) c = getchar();
	sgn = (c == '-') ? -1 : 1;
	ret = (c == '-') ? 0 : (c - '0');
	while (c = getchar(), c >= '0'&&c <= '9') ret = ret * 10 + (c - '0');
	ret *= sgn;
	return 1;
}
template <class T>
inline void pt(T x) {
	if (x < 0) {
		putchar('-');
		x = -x;
	}
	if (x > 9) pt(x / 10);
	putchar(x % 10 + '0');
}
typedef pair<int, int> pii;
typedef long long ll;
const int N = 1005;
const int mod = 1e9 + 7;
const int inf = 1e9;
int Pow(int x, int y) {
	int ans = 1;
	while (y) {
		if (y & 1)ans = (ll)ans*x%mod;
		y >>= 1;
		x = (ll)x*x%mod;
	}return ans;
}
vector<int>G[N];
int n, k;
int dp[N][N], siz[N], lef[N];
int A[N];
int mul(int x, int y) {
	x = (ll)x*y%mod;
	return x;
}
inline void add(int &x, int y) {
	x += y; if (x >= mod)x -= mod;
}
inline void sub(int &x, int y) {
	x -= y; if (x < 0)x += mod;
}
inline void dv(int &x, int y) {
	x = (ll)x*Pow(y, mod - 2) % mod;
}
int g[N];
void dfs(int u, int fa) {
	siz[u] = 1; lef[u] = 0;
	for (auto v : G[u]) {
		if (v == fa)continue;
		dfs(v, u);
		siz[u] += siz[v];
	}
	if (siz[u] == 1) {
		dp[u][0] = 0; dp[u][1] = 1;
		lef[u] = 1;
		return;
	}
	dp[u][0] = 1;
	int x1 = A[siz[u] - 1], x2 = A[siz[u]];
	siz[u] = 0;
	for (auto v : G[u]) {
		if (v == fa)continue;
		for (int i = lef[u] + lef[v]; i <= min(k, siz[u] + siz[v]); i++)g[i] = 0;
		for (int i = lef[u]; i <= min(k, siz[u]); i++)
		{
			for (int j = lef[v]; j <= min(k, siz[v]) && i + j <= k; j++)
			{
				add(g[i + j], mul(dp[v][j], dp[u][i]));
			}
		}
		for (int i = lef[u] + lef[v]; i <= min(k, siz[u] + siz[v]); i++)dp[u][i] = g[i];

		siz[u] += siz[v];
		lef[u] += lef[v];
		dv(x1, A[siz[v]]);
		dv(x2, A[siz[v]]);
	}
	siz[u]++;
	sub(x2, x1);
	for (int i = min(siz[u], k); i >= lef[u]; i--) {
		int tmp = 0;
		add(tmp, mul(dp[u][i], x2));
		if (i - 1 >= lef[u])
		add(tmp, mul(dp[u][i - 1], x1));
		dp[u][i] = tmp;
	}
}
int main() {
	A[0] = 1;
	for (int i = 1; i < N; i++)A[i] = (ll)A[i - 1] * i%mod;
	int T, Cas = 1; rd(T);
	while (T--) {
		rd(n); rd(k);
		for (int i = 1; i <= n; i++)G[i].clear(), memset(dp[i], 0, sizeof dp[i]);
		for (int i = 1, u, v; i < n; i++) {
			rd(u); rd(v);
			G[u].push_back(v); G[v].push_back(u);
		}
		dfs(1, 1);
		printf("Case #%d: ", Cas++);
		pt(dp[1][k]); puts("");
	}
	return 0;
}
/*
99
5 3
1 2
2 3
2 4
1 5

4 2
1 2
2 3
2 4

ans:12

4 3
1 2
2 3
2 4

4 4
1 2
2 3
2 4

*/

Leader in Tree Land

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)

Total Submission(s): 262    Accepted Submission(s): 88

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?1line
describe the roads of tree land.

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

Source

2015 Multi-University Training Contest 7

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-05 23:13:47

HDU 5378 Leader in Tree Land 树形背包的相关文章

hdu 5378 Leader in Tree Land(dp+逆元)

题目链接:hdu 5378 Leader in Tree Land 问题可以理解成N个节点的树,有K个ministers的概率,最后乘上N!.每个节点为ministers的概率即为1 / son(以该节点为根节点的子树包含的节点个数),同样不为ministers的概率为(son-1)/son.所以没有必要考虑树的结构,直接根句子节点的个数转移dp[i][j] dp[i][j] = dp[i-1][j-1] * 1 / son[u] dp[i][j] = dp[i-1][j] * (son[u]-

HDU 5378 Leader in Tree Land

可以用求概率的思想来解决这个问题.令以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]就是所有点中恰好有

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

[概率dp] hdu 5378 Leader in Tree Land

题意: 给你一颗以1位根节点的树,我们定义对于每个子树,节点权值最大的权值记为这个子树的权值,为你将1~n放到这个树里 满足最大权值只有k个的组合数是多少. 思路: 我们可以知道以每个节点为子树,且根节点权值最大的概率是多少,不是的概率是多少. 那么其实问题就变成了 我们在n个物品里面,每个物品拿的概率是pi不拿的概率是1-pi 问你拿k个物品的概率是多少 然后最后乘n!就好了.中间计算运用逆元. 代码: #include"cstdlib" #include"cstring&

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].这样

[2015hdu多校联赛补题]hdu5378 Leader in Tree Land

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5378 题意:给你一棵n个结点的有根树.因为是有根树,那么每个结点可以指定以它为根的子树(后面讨论的子树都是这个).现在我们把标号从1到n的n个minister派驻到这些结点上面(每个结点派驻一人),并规定任一子树中编号最大的minister 为该子树的领导,问你存在多少个不同的领导 解: 引用官方题解: 可以用求概率的思想来解决这个问题.令以i号节点为根的子树为第i棵子树,设这颗子树恰好有sz[i]

J. Leader in Tree Land

#include <iostream> using namespace std; int cas,t = 1,road[1001][1001],n,k,ra,rb,size[1001]; long long sum,dp[1001][1001]; //dp[i][j]表示从1到i节点有j个节点是其字数的最大值 void init() { int i,j; sum = 1; for(i = 1;i <= n;i ++) { sum = (sum*i)%1000000007; size[i]

hdu 1561The more, The Better(树形dp&amp;01背包)

The more, The Better Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 4949    Accepted Submission(s): 2918 Problem Description ACboy很喜欢玩一种战略游戏,在一个地图上,有N座城堡,每座城堡都有一定的宝物,在每次游戏中ACboy允许攻克M个城堡并获得里面的宝

Bestcoder round #65 &amp;&amp; hdu 5593 ZYB&#39;s Tree 树形dp

Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 354    Accepted Submission(s): 100 Problem Description ZYB has a tree with N nodes,now he wants you to solve the numbers of nodes distanced no m