树型DP 2题

博客提及CQOI2009叶子的染色问题,介绍了树中叶子节点的定义,即无后继节点。还涉及树形DP及初始化,此外提到ARC101F并给出转载链接。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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 

转载于:https://www.cnblogs.com/lxzl/p/9556962.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值