• 蓝桥杯 ALGO-4 结点选择 (树形动态规划)


    问题描述

    有一棵 n 个节点的树,树上每个节点都有一个正整数权值。如果一个点被选择了,那么在树上和它相邻的点都不能被选择。求选出的点的权值和最大是多少?

    输入格式

    第一行包含一个整数 n 。

    接下来的一行包含 n 个正整数,第 i 个正整数代表点 i 的权值。

    接下来一共 n-1 行,每行描述树上的一条边。

    输出格式
    输出一个整数,代表选出的点的权值和的最大值。
    样例输入
    5
    1 2 3 4 5
    1 2
    1 3
    2 4
    2 5
    样例输出
    12
    样例说明
    选择3、4、5号点,权值和为 3+4+5 = 12 。
     
    一道最基础的 树形动态规划,今天重温一下,顺便温习一下邻接表的构建过程。
    状态转移方程为:dp[s][0]+=dp[u][1];  dp[s][1]+=max(dp[u][0],dp[u][1]);(u为s的子节点,0表示包含自己的以s为根节点的子树最大值,1表示不包含自己的以s为根节点的子树最大值)
    ac代码如下:
    #include<iostream>
    #include<cstring>
    using namespace std;
    struct edge{
        int e,next;
    }e[300000];
    int head[150000],val[150000];
    int N,M=0;
    void add(int s,int e1){
        e[++M].e=e1;
        e[M].next=head[s];
        head[s]=M;
    }
    long dp[150000][2];
    bool v[150000];
    void dfs(int s){
        dp[s][0]=val[s];
        dp[s][1]=0;
        for(int i=head[s];i!=-1;i=e[i].next){
            int u=e[i].e;
            if(v[u]==0){
                v[u]=1;
                dfs(u);
                dp[s][0]+=dp[u][1];
                dp[s][1]+=max(dp[u][0],dp[u][1]);
                v[u]=0;
            }
        }
    }
    int main(){
        cin>>N;
        int s,e;
        memset(head,-1,sizeof(head));
        for(int i=1;i<=N;i++) cin>>val[i];
        for(int i=1;i<N;i++){
            cin>>s>>e;
            add(s,e);add(e,s);
        }
        int ans=0;
        memset(dp,0,sizeof(dp));
        memset(v,0,sizeof(v));
        v[1]=1;
        dfs(1);
        v[1]=0;
        ans=max(dp[1][0],dp[1][1]);
        cout<<ans<<endl;
        return 0;
    }
     
  • 相关阅读:
    php数据缓存到文件类设计
    php静态文件缓存示例
    php array_merge和“+”的区别和使用《细说php2》
    kafka环境安装及简单使用(单机版)
    Protobuf的上手使用
    Java8新特性概览
    Mock测试框架(Mockito为例)
    Java序列化与反序列化
    系统/项目环境搭建
    关于Tomcat服务器中的协议及请求过程
  • 原文地址:https://www.cnblogs.com/yifan2016/p/5268887.html
Copyright © 2020-2023  润新知