您的位置:首页 > 其它

ZOJ - 3201 Tree of Tree

2015-05-18 21:33 411 查看
题目大意:给一棵节点带权的树,找到一个有k个节点的子树,求这个子树的最大权值

解题思路:树形 DP + 背包,f(i, j) 表示以i为根节点的有j个节点子树的最大权值,然后对i的每个子节点做分组背包,因为对于i的每个儿子,可以选择分 1,2,3…j-1 个节点给它

f(i, j) = max{ max{f(i, j-p) + f(v, p) | 1 <= p < j} | v是i的儿子节点}
ans = max{ f[i][k] | 0 <= i < n && i子树节点个数>=k }


#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
int N, K, ans, DP[105][105], vis[105];
vector <int> A[105];

void init() {
ans = 0;
memset(DP, 0, sizeof(DP));
memset(vis, 0, sizeof(vis));
for (int i = 0; i <= N; i++)
A[i].clear();

for (int i = 0; i < N; i++)
scanf("%d", &DP[i][1]);

int x, y;
for (int i = 0; i < N - 1; i++) {
scanf("%d%d", &x, &y);
A[x].push_back(y);
A[y].push_back(x);
}
}

void DPS(int root) {
vis[root] = 1;
int num = A[root].size();
for (int i = 0; i < num; i++) {
int child = A[root][i];
if (vis[child])
continue;
DPS(child);
for (int j = K; j > 0; j--)
for (int r = 1; r < j; r++)
DP[root][j] = max(DP[root][j], DP[root][j - r] + DP[child][r]);
}
ans = max(ans, DP[root][K]);
}

int main() {
while (scanf("%d%d", &N, &K) != EOF) {
init();
DPS(0);
printf("%d\n", ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: