【題解】[HAOI2015]樹上染色
阿新 • • 發佈:2021-07-09
\(\text{Solution:}\)
考慮對於一個點,從它子樹再中選擇 \(k\) 個黑點的代價:\(e[i].dis \cdot (p-k)*k+(siz[j]-k)*(n-p-siz[j]+k).\)
於是狀態轉移方程就寫好了:
\(dp[x][T]=dp[x][T]=Max(dp[x][T],dp[x][T-k]+dp[j][k]+v*(k*(p-k)+(siz[j]-k)*(n-p-siz[j]+k)))\)
同時注意要記得把子樹中全是白點的情況記錄一下:
\(dp[x][T]+=dp[j][0]+siz[j]*(n-p-siz[j])*v\)
#include<bits/stdc++.h> using namespace std; #define int long long typedef long long ll; const int MAXN=3001; const ll dyx=(1LL<<60); inline ll read(){ ll s=0,w=1; char ch=getchar(); while(!isdigit(ch)){ if(ch=='-')w=-1; ch=getchar(); } while(isdigit(ch)){ s=s*10-48+ch; ch=getchar(); } return s*w; } int n,p,siz[MAXN]; ll dp[MAXN][MAXN]; int head[MAXN],tot; struct E{int nxt,to,dis;}e[MAXN<<1]; inline int Max(int x,int y){return x>y?x:y;} inline int Min(int x,int y){return x<y?x:y;} inline void add(int x,int y,int w){ e[++tot]=(E){head[x],y,w}; head[x]=tot; } void dfs(int x,int fa){ siz[x]=1;dp[x][0]=dp[x][1]=0; for(int i=head[x];i;i=e[i].nxt){ int j=e[i].to; if(j==fa)continue; dfs(j,x); int v=e[i].dis;siz[x]+=siz[j]; for(int T=Min(siz[x],p);T>=0;--T){ if(dp[x][T]!=-1){ dp[x][T]+=dp[j][0]+siz[j]*(n-p-siz[j])*v; } for(int k=Min(T,siz[j]);k;--k){ if(dp[x][T-k]==-1)continue; dp[x][T]=Max(dp[x][T],dp[x][T-k]+dp[j][k]+v*(k*(p-k)+(siz[j]-k)*(n-p-siz[j]+k))); } } } } signed main(){ // freopen("111.txt","r",stdin); n=read(),p=read(); if(n-p<p)p=n-p; for(int i=1;i<n;++i){ int x=read(),y=read(),v=read(); // read(x);read(y);read(v); add(x,y,v);add(y,x,v); } memset(dp,-1,sizeof dp); dfs(1,0); ll ans=dp[1][p]; printf("%lld\n",ans); return 0; }