zoukankan      html  css  js  c++  java
  • codeforces 212E 树上背包

    http://codeforces.com/problemset/problem/212/E

    结论: 两个颜色之和最大值一定是N-1 (根节点不染色,子树染成红或蓝)

    DP[i][j] 表示 i 节点不染色,j 个点染成红色是否可行 (蓝色节点个数可以计算出来)

    剩下的就是背包了,不要忘记对每个点的父亲也进行背包(因为是假设该点为根不染色)

    最后统计答案的时候去掉只有一种颜色的情况

    代码:

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    
    const int maxn = 5010;
    
    int h[maxn],cnt=0;
    
    int n,ans = 0;
    int dp[maxn][maxn],is_red[maxn]; //  i 节点不染色,有 j 个红色点是否可行 
    
    struct E{
        int to,next;
    }e[maxn*2]; 
    
    void add(int u,int v){
        e[++cnt].next = h[u];
        e[cnt].to = v;
        h[u] = cnt;
    }
    
    int sz[maxn];
    
    void dfs(int u,int par){
        sz[u] = 1;
        dp[u][0] = 1;
        
        for(int i=h[u];i!=-1;i=e[i].next){
            int v = e[i].to;
            if(v==par) continue;
            dfs(v,u);
            sz[u] += sz[v];
        }
    
        for(int i=h[u];i!=-1;i=e[i].next){
            int v=e[i].to;
            if(v==par) continue;
            for(int j=n-1;j>=sz[v];--j){ // 0/1 背包 
                dp[u][j] |= dp[u][j-sz[v]]; // 注意一定要或!! 
    //            printf("%d %d %d %d
    ",u,v,j,dp[u][j]);
            }
        }
        
        int s = n - sz[u];
        for(int j=n-1;j>=s;--j){
            dp[u][j] |= dp[u][j-s];
    //        printf("%d %d %d %d
    ",u,par,j,dp[u][j]);
        }
        
        for(int i=1;i<n-1;++i){
            if(dp[u][i] && !is_red[i]){
                ++ans;
                is_red[i] = 1;
            }
        }
    }
    
    ll read(){ int f=1,s=0; char ch = getchar(); while(ch<'0' || ch>'9'){ if(ch=='-') f=-1; else ch = getchar(); } while(ch>='0' && ch<='9'){ s = s * 10 + ch - '0'; ch = getchar(); } return s * f; }
    
    int main(){
        memset(h,-1,sizeof(h)); 
        n = read();
        
        int u,v;
        for(int i=1;i<n;i++){
            u = read(),v = read();
            add(u,v),add(v,u);
        }
    
        dfs(1,0); 
    
        printf("%d
    ",ans);
        
        for(int i=1;i<n-1;i++){
            if(is_red[i]){
                printf("%d %d
    ",i,n-1-i);
            }
        }
    
        return 0;
    }
  • 相关阅读:
    servlet-01
    JavaWeb——文件上传和下载
    tomcat 7.0.94 下载安装步骤
    java 中 contains() containsKey() containsvalue() 使用
    java通过Runtime和Process类调用外部命令
    build.xml编译报错Specified VM install not found: type Standard VM, name jdk1.7.0_45
    微信小程序样式旋转
    微信小程序轮播图组件 swiper,swiper-item及轮播图片自适应
    HTTPS请求
    ztree插件的使用
  • 原文地址:https://www.cnblogs.com/tuchen/p/13764649.html
Copyright © 2011-2022 走看看