树上染色
这是蒟蒻的第一道树形背包,由于不知道套路,几乎全抄的题解(惭愧)。
有点类似于CDQ分治的思想,先处理下级,然后利用下级的数据推本级。
其实我还没有理解透彻,不过贡献一下代码也是有价值的。
#include<bits/stdc++.h> using namespace std; #define int long long const int maxn=2005; int n,m,sz[maxn]; int beg[maxn<<1],nex[maxn<<1],to[maxn<<1],w[maxn<<1],e; int f[maxn][maxn]; inline void add(int x,int y,int z){ e++;nex[e]=beg[x]; beg[x]=e;to[e]=y;w[e]=z; } inline void dfs(int x,int fa){ sz[x]=1,f[x][0]=f[x][1]=0; for(int i=beg[x];i;i=nex[i]) if(to[i]!=fa)dfs(to[i],x),sz[x]+=sz[to[i]]; for(int i=beg[x];i;i=nex[i]) if(to[i]!=fa) for(int j=min(m,sz[x]);j>=0;j--) for(int k=0;k<=min(j,sz[to[i]]);k++) if(f[x][j-k]!=-1) f[x][j]=max(f[x][j],f[x][j-k]+f[to[i]][k]+w[i]*(k*(m-k)+(sz[to[i]]-k)*(n-m-sz[to[i]]+k))); } signed main(){ cin>>n>>m; int x,y,z; for(int i=1;i<n;i++){ scanf("%lld%lld%lld",&x,&y,&z); add(x,y,z),add(y,x,z); } memset(f,-1,sizeof(f)); dfs(1,0); printf("%lld\n",f[1][m]); return 0; }
深深地感到自己的弱小。