BZOJ1304: [CQOI2009]叶子的染色

来源:互联网 发布:sql注入点判断 编辑:程序博客网 时间:2024/04/28 16:34

可以证明根向任意方向移动一格,答案不变,所以根取哪个点都行
然后treedp

code:

#include<set>#include<map>#include<deque>#include<queue>#include<stack>#include<cmath>#include<ctime>#include<bitset>#include<string>#include<vector>#include<cstdio>#include<cstdlib>#include<cstring>#include<climits>#include<complex>#include<iostream>#define ll long longusing namespace std;const int maxn = 11000;int n,m;struct edge{    int y,nex;    edge(){}    edge(const int _y,const int _nex){y=_y;nex=_nex;}}a[maxn<<1]; int len,fir[maxn];inline void ins(const int x,const int y){a[++len]=edge(y,fir[x]);fir[x]=len;}int f[maxn][2],c[maxn];void dfs(const int x,const int ff){    f[x][0]=f[x][1]=1;    if(x<=m) { f[x][c[x]^1]=maxn; return; }    for(int k=fir[x];k;k=a[k].nex)    {        const int y=a[k].y;        if(y!=ff)        {            dfs(y,x);            f[x][0]+=min(f[y][0]-1,f[y][1]);            f[x][1]+=min(f[y][1]-1,f[y][0]);        }    }}int main(){    scanf("%d%d",&n,&m);    for(int i=1;i<=m;i++) scanf("%d",&c[i]);    for(int i=1;i<n;i++)    {        int x,y; scanf("%d%d",&x,&y);        ins(x,y); ins(y,x);    }    dfs(m+1,0);    printf("%d\n",min(f[m+1][0],f[m+1][1]));    return 0;}