[Luogu P1122]最大子树和 (简单树形DP)

题面

传送门:https://www.luogu.org/problemnew/show/P1122


Solution

这是一道简单的树形DP题。

首先,我们可以转换一下题面,可以发现,题目要求我们求出一颗树上的最大联通子图

因为我们是在树上取的,实际上就是取一颗子树。

这个就是最基础的树形DP模型了。

我们可以设f[i]表示我们选的子图以i为根所能取的子树的最大值

转移是:

f[i] = beauty[i] + xigema(max(f[j],0))

(也就是一颗树的孩子所能取的子树,如果它孩子为根的子树>0,就取它,否则不取)

答案就是最大的f[i]


Code

//Luogu P1122 最大子树和
//Jul,30th,2018
//树形DP
#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;
long long read()
{
    long long x=0,f=1; char c=getchar();
    while(!isdigit(c)){if(c==‘-‘) f=-1;c=getchar();}
    while(isdigit(c)){x=x*10+c-‘0‘;c=getchar();}
    return x*f;
}
const int N=16000+100;
const int inf=0x3f3f3f3f;
vector <int> e[N];
int n,beauty[N];
long long f[N];
bool vis[N];
long long dfs(int x)
{
    f[x]=beauty[x];
    vis[x]=true;
    for(int i=0;i<int(e[x].size());i++)
        if(vis[e[x][i]]==false)
            f[x]=max(f[x],f[x]+dfs(e[x][i]));
    return f[x];
}
int main()
{
    n=read();
    for(int i=1;i<=n;i++)
        e[i].reserve(4);
    for(int i=1;i<=n;i++)
        beauty[i]=read();
    for(int i=1;i<n;i++)
    {
        int s=read(),t=read();
        e[s].push_back(t);
        e[t].push_back(s);
    }

    dfs(1);

    long long ans=-inf;
    for(int i=1;i<=n;i++)
        ans=max(ans,f[i]);
    printf("%lld",ans);
    return 0;
}

正解(C++)

原文地址:https://www.cnblogs.com/GoldenPotato/p/9393376.html

时间: 2024-10-07 05:42:18

[Luogu P1122]最大子树和 (简单树形DP)的相关文章

P1122 最大子树和(树形dp)

P1122 最大子树和 题目描述 小明对数学饱有兴趣,并且是个勤奋好学的学生,总是在课后留在教室向老师请教一些问题.一天他早晨骑车去上课,路上见到一个老伯正在修剪花花草草,顿时想到了一个有关修剪花卉的问题.于是当日课后,小明就向老师提出了这个问题: 一株奇怪的花卉,上面共连有N 朵花,共有N-1条枝干将花儿连在一起,并且未修剪时每朵花都不是孤立的.每朵花都有一个"美丽指数",该数越大说明这朵花越漂亮,也有"美丽指数"为负数的,说明这朵花看着都让人恶心.所谓"

csu 2014 summer training day 3 简单树形dp

FZU 2157 题意:树上的节点可以打上0或1的标记,树的权值由两部分呢组成,点权和边权,有00.01.10.11四种组合的边权, 问最小权值和.以1节点为树根 分析:dp[x][0]表示x标记0后的最小的权值,dp[x][1]同理 那么每次可以计算dp[x][0],dp[x][1]: 例如dp[x][1]=min(dp[son][0]+lab[0][1]+val[1],dp[son][1]+bal[1][1]+val[1]); 具体看代码. 用bfs写的分层,深搜代码更简洁 1 #inclu

hdu 1520Anniversary party(简单树形dp)

Anniversary party Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 4310    Accepted Submission(s): 1976 Problem Description There is going to be a party to celebrate the 80-th Anniversary of the

sgu 143 Long live the Queen 简单树形dp

// sgu 143  Long live the Queen 简单树形dp // // 题意:在树上选一个连通字图,使得节点的权值之和最大 // f[i] 表示以该节点为根的字图权值之和的最大值 // 则有 f[i] = w[i] + sigma(max(0,f[j])) i是j的父节点 // 最后在所有的f中挑个最大值就是答案.... #include <algorithm> #include <bitset> #include <cassert> #include

Luogu P1122 最大子树和 树形DP

题目描述 小明对数学饱有兴趣,并且是个勤奋好学的学生,总是在课后留在教室向老师请教一些问题.一天他早晨骑车去上课,路上见到一个老伯正在修剪花花草草,顿时想到了一个有关修剪花卉的问题.于是当日课后,小明就向老师提出了这个问题: 一株奇怪的花卉,上面共连有N 朵花,共有N-1条枝干将花儿连在一起,并且未修剪时每朵花都不是孤立的.每朵花都有一个"美丽指数",该数越大说明这朵花越漂亮,也有"美丽指数"为负数的,说明这朵花看着都让人恶心.所谓"修剪",意为

[luogu]P1352 没有上司的舞会[树形DP]

本Lowbee第一次写树形DP啊,弱...一个变量写错半天没看出来...... 题目描述 某大学有N个职员,编号为1~N.他们之间有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是子结点的直接上司.现在有个周年庆宴会,宴会每邀请来一个职员都会增加一定的快乐指数Ri,但是呢,如果某个职员的上司来参加舞会了,那么这个职员就无论如何也不肯来参加舞会了.所以,请你编程计算,邀请哪些职员可以使快乐指数最大,求最大的快乐指数. 输入输出格式 输入格式: 第一行一个整数N.(1<=N<=600

【Luogu】P1131时态同步(树形DP)

题目链接 甚矣吾衰也!这么简单的DP我都不会了 太恐怖了 树形DP,从子树里选出时间最长的来,剩下的调到这个最长时间即可. #include<cstdio> #include<cctype> #include<algorithm> #include<cstring> using std::max; inline long long read(){ long long num=0,f=1; char ch=getchar(); while(!isdigit(c

HDU 3899 简单树形DP

题意:一棵树,给出每个点的权值和每条边的长度, 点j到点i的代价为点j的权值乘以连接i和j的边的长度.求点x使得所有点到点x的代价最小,输出 虽然还是不太懂树形DP是什么意思,先把代码贴出来把. 这道题目的做法是:先进行一次DFS,以每个节点为根,求出它下面节点到它的数量和. 再进行一次DFS,以每个节点为根,求出它下面节点到它的花费总和. source code: #pragma comment(linker, "/STACK:16777216") //for c++ Compile

UVALive - 2038 Strategic game (无向+记忆化+简单树形DP)

题目链接:https://vjudge.net/problem/UVALive-2038 题意:给定一棵树,选择尽量少的点,使得每个没有选中的结点至少和一个已经选中的结点相邻.输出最少需要选择的节点数.思路:经典的二分图最小顶点覆盖, 也是经典的树形 DP AC代码: #include<stdio.h> #include<string.h> #include<vector> #include<algorithm> using namespace std; c