1. 程式人生 > >HDU 5378 Leader in Tree Land 樹形揹包

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