【HAOI2015】树上染色

链接

看到题想了想,或许可以算每个子树,就像普通树形dp.

然后搞出了 dp [ i ] [ j ] ,g [ i ] [ j ] ,cnt [ i ] [ j ]...

并且我可以严谨的证明这玩意是错的。

然后移步题解,意识到树性DP除了可以按点统计,还可以按边来看。

考虑枚举到一条边 ( u , v ) ,对答案的贡献就是 black [ u ] * black [ v ] + white [ u ] * white [ v ] * w [ i ].z;

很自然,我们设 dp [ i ] [ j ] 为以 i 为根的子树内有 j 个黑节点的最大收益。

简单转移一下就好。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<string>
 4 #include<cstring>
 5 using namespace std;
 6 const int N=2005;
 7 typedef long long LL;
 8 
 9 inline LL read(){
10     LL x=0,f=1;char ch=getchar();
11     while(ch<'0'||ch>'9'){
12         if(ch=='-')f=-1;
13         ch=getchar();
14     }
15     while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
16     return x*f;
17 }
18 
19 int n,kk;
20 LL x,y,z;
21 struct node{
22     LL y,nxt,z;
23 }e[N<<1];
24 int tot=0,h[N];
25 
26 inline void ad(LL x,LL y,LL z){
27     ++tot;
28     e[tot].y=y;e[tot].z=z;e[tot].nxt=h[x];h[x]=tot;
29 }
30 
31 LL dp[N][N];
32 int sz[N];
33 
34 inline void dfs(int x,int f){
35     sz[x]=1;
36     for(int i=h[x];i;i=e[i].nxt){
37         int y=e[i].y;
38         if(y==f)continue;
39         dfs(y,x);sz[x]+=sz[y];
40     }
41 }
42 
43 inline void solve(int x,int f){
44     memset(dp[x],-1,sizeof(dp[x]));dp[x][0]=dp[x][1]=0;
45     for(int i=h[x];i;i=e[i].nxt){
46         int y=e[i].y;
47         if(y==f)continue;
48         solve(y,x);
49         for(int j=min(kk,sz[x]);j>=0;--j){
50             for(int k=0;k<=min(j,sz[y]);++k){
51                 if(~dp[x][j-k]){
52                     LL val=((kk-k)*k+(n-sz[y]-(kk-k))*(sz[y]-k))*e[i].z;
53                     dp[x][j]=max(dp[x][j],dp[y][k]+dp[x][j-k]+val);
54                 }
55             }
56         }
57     }
58 }
59 int main(){
60     n=read();kk=read();
61     for(int i=1;i<n;++i){
62         x=read();y=read();z=read();
63         ad(x,y,z);ad(y,x,z);
64     }
65     dfs(1,1);
66     solve(1,1);
67     cout<<dp[1][kk];
68 } 

这里的初值为什么要设为-1?

因为转移是倒序的,所以第一次转移时可能发生dp[x][j-k]无值可传的现象,这样统计的答案就不是实际的值了。

做DP问题要关注状态是否真实,真实就是指合法的从已知状态转移过来。

转了假状态,会使答案变得fake。

posted @ 2019-08-02 16:17  Chiyo小朋友  阅读(132)  评论(0编辑  收藏  举报