BZOJ 1369 树形DP
思路:
f[i][j] 表示节点i 染成j时 子树的最小权值
(我会猜这个j很小 你打我吖~)
随便DP一发就好了 (证明我也不会)
//By SiriusRen
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=20050,inf=0x3f3f3f3f;
int v[N],next[N],first[N],tot,n,xx,yy,f[N][21],ans=inf;
void add(int x,int y){v[++tot]=y,next[tot]=first[x],first[x]=tot;}
void dfs(int x,int fa){
for(int i=1;i<=20;i++)f[x][i]=i;
for(int i=first[x];i;i=next[i])if(v[i]!=fa)dfs(v[i],x);
for(int j=1;j<=20;j++)
for(int i=first[x];i;i=next[i])if(v[i]!=fa){
int temp=inf;
for(int k=1;k<=20;k++)if(j!=k)temp=min(temp,f[v[i]][k]);
f[x][j]+=temp;
}
}
int main(){
scanf("%d",&n);
for(int i=1;i<n;i++)scanf("%d%d",&xx,&yy),add(xx,yy),add(yy,xx);
dfs(1,-1);
for(int i=1;i<=20;i++)ans=min(ans,f[1][i]);
printf("%d\n",ans);
}