题意:
给定N≤5×104一棵无根树,每个节点个权值,且可能有陷阱
现在从任意一个节点出发,如果无路可走或者踩到C≤3个陷阱就停止了
求能获得最大的权值和
分析:
树形dp,经典题,蓝儿我并不会做
f[u][i][0/1]:=以u为根的子树中,从有无陷阱的节点出发,且经过i个陷阱的最大权值和
我们来考虑下ans的构成,枚举2颗子树接起来,然后就是枚举各自经过的陷阱数,边界情况很多−−
需要注意的是枚举其中一颗子树不能包括另一个子树,树形dp常见技巧了
更新的时候,对于f[v][j][0]要往f[u][j+trap[u][0]更新的话,j必须<c,不然就停了
对于f[v][j][1]要往f[u][j+trap[u][1]更新的话,j可以=c,因为f[u][c][1]构成答案的时候,可以作为终点
代码:
//
// Created by TaoSama on 2016-02-29
// Copyright (c) 2016 TaoSama. All rights reserved.
//
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <set>
#include <vector>
using namespace std;
#define pr(x) cout << #x << " = " << x << " "
#define prln(x) cout << #x << " = " << x << endl
const int N = 1e5 + 10, INF = 0x3f3f3f3f, MOD = 1e9 + 7;
typedef long long LL;
int n, c, val[N], trap[N];
vector<int> G[N];
LL f[N][5][2],
ans; //u为根子树, 起点有无陷阱, 且经过j个陷阱的最大值
void getMax(LL& x, LL y) {
if(y > x) x = y;
}
void dfs(int u, int fa) {
f[u][trap[u]][trap[u]] = val[u];
// getMax(ans, val[u]); n >= 2 no need to concern single node
for(int v : G[u]) {
if(v == fa) continue;
dfs(v, u);
for(int i = 0; i <= c; ++i) {
for(int j = 0; i + j <= c; ++j) {
getMax(ans, f[u][i][1] + f[v][j][1]);
if(i < c) getMax(ans, f[u][i][0] + f[v][j][1]);
if(j < c) getMax(ans, f[u][i][1] + f[v][j][0]);
if(i + j < c) getMax(ans, f[u][i][0] + f[v][j][0]);
}
}
for(int i = 0; i <= c; ++i) {
if(i < c) getMax(f[u][i + trap[u]][0], f[v][i][0] + val[u]);
getMax(f[u][i + trap[u]][1], f[v][i][1] + val[u]);
}
}
}
int main() {
#ifdef LOCAL
freopen("C:\\Users\\TaoSama\\Desktop\\in.txt", "r", stdin);
// freopen("C:\\Users\\TaoSama\\Desktop\\out.txt","w",stdout);
#endif
ios_base::sync_with_stdio(0);
int t; scanf("%d", &t);
while(t--) {
scanf("%d%d", &n, &c);
for(int i = 1; i <= n; ++i) {
G[i].clear();
scanf("%d%d", val + i, trap + i);
}
for(int i = 1; i < n; ++i) {
int u, v; scanf("%d%d", &u, &v);
G[++u].push_back(++v);
G[v].push_back(u);
}
ans = 0;
memset(f, 0xc0, sizeof f);
dfs(1, -1);
printf("%I64d\n", ans);
}
return 0;
}