正题
题目链接:https://www.luogu.org/problem/P4395
题目大意
一棵树,每个节点填一个正整数,要求相邻的节点数字不同,求所有节点的和最小。
解题思路
根据四色定理,我们可以知道用四个数字一定可以填完,所有填的数字只有1∼41\sim 41∼4。
设fi,jf_{i,j}fi,j表示节点iii的颜色为jjj,它的子树的最小价值和。
然后树形dpdpdp即可。
codecodecode
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=11000;
struct node{int to,next;
}a[2*N];
int n,tot,ls[N],f[N][5];
void addl(int x,int y)
{a[++tot].to=y;a[tot].next=ls[x];ls[x]=tot;
}
void dp(int x,int fa)
{for(int i=ls[x];i;i=a[i].next){int y=a[i].to;if(y==fa) continue;dp(y,x);for(int j=1;j<=4;j++){int z=1e9;for(int k=1;k<=4;k++)if(j!=k)z=min(z,f[y][k]);f[x][j]+=z;}}for(int i=1;i<=4;i++)f[x][i]+=i;
}
int main()
{scanf("%d",&n);for(int i=1;i<n;i++){int x,y;scanf("%d%d",&x,&y);addl(x,y);addl(y,x);}dp(1,1);printf("%d",min(min(f[1][1],f[1][2]),min(f[1][3],f[1][4])));
}