题目链接:传送门
题意:
给定一棵树,树上的每个点有一个权值,这个点可能有锁也可能没有锁,一个节点不能被走两次,如果你被锁了C次那么你就不能继续往下走了,可以自己选择起点,问所能得到的最大值是多少。
思路一:
直接根据题意,然后从叶节点开始暴力搜,由于题目的数据比较弱所以这种方法可以过。
代码如下:
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <vector>
using namespace std;
const int maxn = 50010;
int n,c;
struct Graph {
vector<int >vc[maxn];
bool vis[maxn];
int lock[maxn];
int val[maxn];
void init() {
memset(lock,0,sizeof(lock));
for(int i=0; i<n; i++)
vc[i].clear();
}
void add(int u,int v){
vc[u].push_back(v);
vc[v].push_back(u);
}
int dfs(int u,int pre,int num){
vis[u]=1;
int sum = val[u];
num+=lock[u];
if(num==c) return sum;
int tmp = 0;
for(int i=0;i<vc[u].size();i++){
int v=vc[u][i];
if(vis[v]||v==pre) continue;
tmp=max(tmp,dfs(v,u,num));
}
return sum+tmp;
}
}G;
int main() {
int t;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&c);
G.init();
for(int i=0;i<n;i++)
scanf("%d%d",&G.val[i],&G.lock[i]);
for(int i=0;i<n-1;i++){
int u,v;
scanf("%d%d",&u,&v);
G.add(u,v);
}
int ans = 0;
for(int i=0;i<n;i++){
if(G.vc[i].size()==1){
memset(G.vis,0,sizeof(G.vis));
ans = max(ans,G.dfs(i,0,0));
}
}
printf("%d\n",ans);
}
return 0;
}
设dp[u][j][k],表示从u孩子到u,被锁了j次起点有锁/没锁的最大值。然后dp[u][j+lock[u]][k]= max(dp[v][j][k]+val[u]) v为u的孩子。
代码如下:
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <vector>
using namespace std;
const int maxn = 50010;
int n,c;
int max2(int x, int y) {
return x > y ? x : y;
}
struct Graph {
vector<int >vc[maxn];
int dp[maxn][4][2];
bool vis[maxn];
int lock[maxn];
int val[maxn];
int ans;
void init() {
ans = 0;
for(int i=0; i<n; i++) {
for(int j=0; j<4; j++) {
for(int l=0; l<2; l++)
dp[i][j][l] = -99999999;
}
}
for(int i=0; i<n; i++)
vc[i].clear();
}
void add(int u,int v) {
vc[u].push_back(v);
vc[v].push_back(u);
}
void dfs(int u,int pre) {
dp[u][lock[u]][lock[u]]=val[u];
for(int i=0; i<vc[u].size(); i++) {
int v = vc[u][i];
if(v==pre) continue;
dfs(v,u);
for(int j=0; j<=c; j++) {
for(int k=0; k+j<=c; k++) {
ans = max2(ans,dp[u][j][1]+dp[v][k][1]);
if(j+k<c) ans = max2(ans,dp[u][j][0]+dp[v][k][0]);
ans = max2(ans,dp[u][j][0]+dp[v][k][1]);
ans = max2(ans,dp[u][j][1]+dp[v][k][0]);
}
}
for(int j=0; j<c; j++) {
dp[u][j+lock[u]][0]=max2(dp[u][j+lock[u]][0],dp[v][j][0]+val[u]);
dp[u][j+lock[u]][1]=max2(dp[u][j+lock[u]][1],dp[v][j][1]+val[u]);
}
if(lock[u]==0) dp[u][c][1] = max2(dp[u][c][1],dp[v][c][1]+val[u]);
}
}
} G;
int main() {
int t;
scanf("%d",&t);
while(t--) {
scanf("%d%d",&n,&c);
G.init();
for(int i=0; i<n; i++)
scanf("%d%d",&G.val[i],&G.lock[i]);
for(int i=0; i<n-1; i++) {
int u,v;
scanf("%d%d",&u,&v);
G.add(u,v);
}
G.dfs(0,-1);
printf("%d\n",G.ans);
}
return 0;
}