zoukankan      html  css  js  c++  java
  • CQOI2009 叶子的染色

    题目链接:戳我

    最近几天真的是没有智商了,今天竟然被这种题卡住了。。。

    树形DP。

    (f[i][0/1])表示以i为根的子树中,最后一个染色的节点染色为0/1,最少需要染色的节点数目。

    我们考虑从下往上DP,就可以消除后效性了。对于一个节点来说,如果它的子节点最后一个节点染的颜色和它的最后一个一样,它自然不需要染,直接累加答案即可。但是如果不一样,他自己还需要染色,所以要+1。

    对于叶子节点,如果染0,那么1就要置成无穷大,这样才可以通过取min操作排除掉染1这种不合法情况。染1同理。

    代码如下:

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #define MAXN 100010
    using namespace std;
    int n,m,t;
    int head[MAXN],f[MAXN][2],c[MAXN];
    struct Edge{int nxt,to;}edge[MAXN<<1];
    inline void add(int from,int to){edge[++t].nxt=head[from],edge[t].to=to,head[from]=t;}
    void dfs(int x,int pre)
    {
        if(x<=n)
        {
            f[x][c[x]]=0,f[x][c[x]^1]=0x3f3f3f3f;
            return;
        }
        for(int i=head[x];i;i=edge[i].nxt)  
    	{
    		int v=edge[i].to;
    		if(v!=pre)
    	    {
    			dfs(v,x);
    	        f[x][0]+=min(f[v][0],f[v][1]+1);
    	        f[x][1]+=min(f[v][1],f[v][0]+1);
    	    }
    	}
    }
    int main()
    {
        #ifndef ONLINE_JUDGE
    	freopen("ce.in","r",stdin);
    	#endif
    	scanf("%d%d",&m,&n);
        int a,b;
        for(int i=1;i<=n;i++)scanf("%d",&c[i]);
        for(int i=1;i<m;i++)scanf("%d%d",&a,&b),add(a,b),add(b,a);
        dfs(m,0);
        printf("%d",min(f[m][0],f[m][1])+1);
        return 0;
    }
    
     
    
  • 相关阅读:
    页面get请求 中文参数方法乱码问题
    java版ftp简易客户端(可以获取文件的名称及文件大小)
    文件下载
    kafka:一个分布式消息系统
    Executor的线程代码
    验证码的生成
    二维码的简单实现
    rsync实现大致流程描述
    C++中模板生成时机
    gcc虚函数表生成时机
  • 原文地址:https://www.cnblogs.com/fengxunling/p/10355707.html
Copyright © 2011-2022 走看看