• 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;
    }
  • 相关阅读:
    dedecms调用指定栏目名称,链接
    修改 Dedecms 文档文章标题长度的方法
    dedeCMS的arclist标签中limit是什么意思
    DedeCms织梦系统[field:description /]标签如何限制字数?
    mysql 如何更改root密码
    允许phpmyadmin空密码登录的配置方法
    Apache启动失败解决办法
    Apache 配置多域名、二级域名
    使用Auto Layout中的VFL(Visual format language)--代码实现自动布局
    使用UITextField自动格式化银行卡号
  • 原文地址:https://www.cnblogs.com/tuchen/p/13764649.html
Copyright © 2020-2023  润新知