AT_abc416_f [ABC416F] Paint Tree 2 题解
违规用户名1045961 · · 题解
纪念我的第一道独自做的蓝色树 DP。
发现
为了方便状态转移,考虑将每颗子树分三种情况处理:不选根、选根但是不能连到上面、选根并能连到上面。
转移很暴力,设点
前三个转移表示
状态
#include <bits/stdc++.h>
using namespace std;
using ll= long long;
const int N=200005;
vector<int> g[N];
int n,k,a[N];
ll dp[N][3][6];
ll ry(int u,int x) {
return max({dp[u][0][x],dp[u][1][x],dp[u][2][x]});
}
void upd(ll& x,ll y) {
if(y>x) x=y;
}
void dfs(int u,int fa) {
for(int i=0;i<3;i++)
for(int j=0;j<=k;j++)
dp[u][i][j]=-1e16;
dp[u][0][0]=0;
ll la[3][6];
for(int& v: g[u]) if(v!=fa) {
dfs(v,u);
for(int i=0;i<3;i++)
for(int j=0;j<=k;j++)
la[i][j]=dp[u][i][j];
for(int x=1;x<=k;x++) {
for(int y=1;y<=x;y++) {
upd(dp[u][0][x],la[0][x-y]+ry(v,y));
upd(dp[u][2][x],la[2][x-y]+ry(v,y));
upd(dp[u][2][x],la[0][x-y]+dp[v][2][y]+a[u]);
upd(dp[u][1][x],la[1][x-y]+ry(v,y));
upd(dp[u][1][x],la[2][x-y+1]+dp[v][2][y]);
}
}
}
for(int i=1;i<=k;i++)
upd(dp[u][2][i],dp[u][0][i-1]+a[u]);
}
int main() {
cin.tie(nullptr)->sync_with_stdio(false);
cin>>n>>k;
for(int i=1;i<=n;i++)
cin>>a[i];
for(int u,v,i=1;i<n;i++) {
cin>>u>>v;
g[u].push_back(v);
g[v].push_back(u);
}
dfs(1,0);
ll ans=-1e16;
for(int i=0;i<=k;i++)
upd(ans,ry(1,i));
cout<<ans;
return 0;
}
:::