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 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 n1line describe the roads of tree land.

T=10,1n1000,1kn
 

Output
For each test case, output one line. The output format is Case #xansx 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
 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章