BZOJ1304: [CQOI2009]叶子的染色

时间:2023-03-09 19:49:19
BZOJ1304: [CQOI2009]叶子的染色

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1304

树形dp。

可以发现其实根选在哪里都是没有问题的。

f[u][0],f[u][1],f[u][2]分别表示以u为根的子树全部满足条件,有0节点没有满足条件和有1节点没有满足条件。

然后就转移就好了。。

#include<cstring>
#include<iostream>
#include<cstdio>
#include<map>
#include<cmath>
#include<algorithm>
#define rep(i,l,r) for (int i=l;i<=r;i++)
#define down(i,l,r) for (int i=l;i>=r;i--)
#define clr(x,y) memset(x,y,sizeof(x))
#define maxn 50050
#define inf 2000000000
#define mm 1000000007
using namespace std;
struct data{int obj,pre;
}e[maxn*];
int head[maxn],f[maxn][],a[maxn],d[maxn],tot,n,m;
int read(){
int x=,f=; char ch=getchar();
while (!isdigit(ch)) {if (ch=='-') f=-; ch=getchar();}
while (isdigit(ch)) {x=x*+ch-''; ch=getchar();}
return x*f;
}
void insert(int x,int y){
e[++tot].obj=y; e[tot].pre=head[x]; head[x]=tot;
}
void dfs(int u,int fa){
int tmp=,tmp1=,tmp2=,s1=,s2=;
if (a[u]!=-) {
f[u][]=;
if (a[u]==) f[u][]=,f[u][]=;
if (a[u]==) f[u][]=,f[u][]=;
return;
}
for (int j=head[u];j;j=e[j].pre){
int v=e[j].obj;
if (v!=fa){
dfs(v,u);
s1=s1+f[v][]; s2=s2+f[v][]; tmp=tmp+f[v][];
tmp1+=min(f[v][],f[v][]); tmp2+=min(f[v][],f[v][]);
}
}
f[u][]=min(tmp,min(s1+,s2+));
f[u][]=min(tmp1,tmp2+);
f[u][]=min(tmp1+,tmp2);
}
int main(){
n=read(); m=read();
clr(a,-);
rep(i,,m) a[i]=read();
rep(i,,n-){
int x=read(),y=read();
d[x]++; d[y]++;
insert(x,y); insert(y,x);
}
rep(i,,n) if (d[i]>=){
dfs(i,); printf("%d\n",f[i][]); break;
}
return ;
}