树形DP

问题:

算法训练 结点选择  
时间限制:1.0s   内存限制:256.0MB
问题描述

有一棵 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 。
数据规模与约定

对于20%的数据, n <= 20。

对于50%的数据, n <= 1000。

对于100%的数据, n <= 100000。

权值均为不超过1000的正整数。


分析:和MIT的课后题 Party 一样

算法:根节点a,它的子节点为bi。。每个节点保留着两个值,I和N作为选与不选的情况下的最大值

则如果a点选择,则I=sum(N(bi)))+value-of-a;

如果a点不选,则M=sum(max ( I(bi) , M(bi) ) );

由此递归

数据结构选择邻接表存储,也可以选择二叉树存储

代码:


#include <iostream>
#include <string.h>
#include <vector>
using namespace std;
#define maxn 100002
struct Po{
    vector<int> xl;
    int I,N;
}s[maxn];
//vector<int> s[maxn];
int vis[maxn];
int a[maxn];
void fun(int t){
    vis[t]=1;
    int m1=a[t],m2=0;
    for(int i=0;i<s[t].xl.size();i++){
        if(!vis[s[t].xl[i]]){
            fun(s[t].xl[i]);
            m1+=s[s[t].xl[i]].N;
            m2 += max(s[s[t].xl[i]].N,s[s[t].xl[i]].I);
        }
    }
    s[t].I=m1;
    s[t].N=m2;
}

int main(){
    memset(vis,0,sizeof(vis));
    int n;
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i];
    }int a1,a2;
    for(int i=1;i<n;i++){
        cin>>a1>>a2;
        s[a1].xl.push_back(a2);
        s[a2].xl.push_back(a1);
    }
    int m1=a[1],m2=0;
    vis[1]=1;
    for(int i=0;i<s[1].xl.size();i++){
        fun(s[1].xl[i]);
        m1+=s[s[1].xl[i]].N;
        m2 += max(s[s[1].xl[i]].N,s[s[1].xl[i]].I);
    }
    cout<<max(m1,m2)<<endl;


return 0;}







评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值