[BZOJ4033][HAOI2015]树上染色 树形DP

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=4033

我们考虑用f[i][j]记录以第i个节点为根的子树,把j个节点染成黑色对最终的答案的最大贡献。

在合并子树更新状态的时候,只需要考虑根与这棵子树的连边对最终答案的贡献即可,因为边的贡献只与两边点的数目有关。

注意更新状态时要像背包一样倒着更新。

复制代码
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 typedef long long ll;
 6 int inline readint(){
 7     int Num;char ch;
 8     while((ch=getchar())<'0'||ch>'9');Num=ch-'0';
 9     while((ch=getchar())>='0'&&ch<='9') Num=Num*10+ch-'0';
10     return Num;
11 }
12 int N,K;
13 int to[4010],ne[4010],fir[2010],cnt=0;
14 ll w[4010];
15 void Add(int a,int b,int c){
16     to[++cnt]=b;
17     w[cnt]=c;
18     ne[cnt]=fir[a];
19     fir[a]=cnt;
20 }
21 int siz[2010];
22 ll f[2010][2010];
23 void Dfs(int x,int fa){
24     siz[x]=1;
25     f[x][0]=f[x][1]=0;
26     for(int i=fir[x];i!=-1;i=ne[i]){
27         int v=to[i];
28         if(v==fa) continue;
29         Dfs(v,x);
30         for(int j=siz[x];j>=0;j--)
31             for(int k=siz[v];k>=0;k--)
32                 f[x][j+k]=max(f[x][j+k],f[x][j]+f[v][k]+w[i]*(K-k)*k+w[i]*(N-siz[v]-K+k)*(siz[v]-k));
33         siz[x]+=siz[v];
34     }
35 }
36 int main(){
37     N=readint();
38     K=readint();
39     memset(fir,-1,sizeof(fir));
40     for(int i=1;i<N;i++){
41         int a=readint(),
42             b=readint(),
43             c=readint();
44         Add(a,b,c);
45         Add(b,a,c);
46     }
47     Dfs(1,0);
48     printf("%lld\n",f[1][K]);
49     return 0;
50 }
复制代码

 

posted @   halfrot  阅读(204)  评论(0编辑  收藏  举报
编辑推荐:
· .NET Core 托管堆内存泄露/CPU异常的常见思路
· PostgreSQL 和 SQL Server 在统计信息维护中的关键差异
· C++代码改造为UTF-8编码问题的总结
· DeepSeek 解答了困扰我五年的技术问题
· 为什么说在企业级应用开发中,后端往往是效率杀手?
阅读排行:
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 推荐几款开源且免费的 .NET MAUI 组件库
· 实操Deepseek接入个人知识库
· 易语言 —— 开山篇
· Trae初体验
点击右上角即可分享
微信分享提示