树型DP 2题

CQOI2009 叶子的染色

树里的定义:叶子节点(1-n)没有后继节点。

然后树形DP

dp[r][0]+=min(dp[x][0]-1,min(dp[x][1],dp[x][2]));
dp[r][1]+=min(dp[x][1]-1,min(dp[x][0],dp[x][2]));
dp[r][2]+=min(dp[x][0],min(dp[x][1],dp[x][2]));

初始化

叶子
dp[r][c[r]]=1;dp[r][2]=dp[r][1^c[r]]=inf;

非叶子 
dp[r][0]=dp[r][1]=1;dp[r][2]=0;

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=1e4+33;
#define ll long long
const ll inf=1e9;
ll c[N],dp[N][3],tot,f[N],sum[N],root,n,m;
struct re{
    int v;
    int nex;
};
re e[N*2];
void dfs(int r,int fath){
    bool az=1;
    for(int i=f[r];i;i=e[i].nex){
    int x=e[i].v;
    if(x==fath)continue;
    dfs(x,r);
    az=0;
    }
    if(az){dp[r][c[r]]=1;dp[r][2]=dp[r][1^c[r]]=inf;return;}
    dp[r][0]=dp[r][1]=1;
    dp[r][2]=0;
    for(int k=f[r];k;k=e[k].nex){
    int x=e[k].v;
    if(x==fath)continue;
    dp[r][0]+=min(dp[x][0]-1,min(dp[x][1],dp[x][2]));
    dp[r][1]+=min(dp[x][1]-1,min(dp[x][0],dp[x][2]));
    dp[r][2]+=min(dp[x][0],min(dp[x][1],dp[x][2]));
    }
}
int main()
{    //freopen("p.in","r",stdin);
    cin>>m>>n;
    for(int i=1;i<=n;i++)cin>>c[i];
    for(int i=1;i<=m-1;i++)
    { int a,b;
      cin>>a>>b;
      sum[a]++;sum[b]++;
      tot++;
      e[tot].v=b;
      e[tot].nex=f[a];
      f[a]=tot;
      tot++;
      e[tot].v=a;
      e[tot].nex=f[b];
      f[b]=tot;
}
    for(int i=1;i<=m;i++)if(sum[i]>1){root=i;break;}
    int ywx;
    dfs(root,-1);
    cout<<min(min(dp[root][0],dp[root][1]),dp[root][2]);
    return 0;
}
View Code

ARC101F 

posted @ 2018-08-29 21:25  周栎  阅读(104)  评论(0编辑  收藏  举报