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
 

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