【Luogu】P1122最大子树和(DFS,树上DP)

题目链接

感觉自己DP好烂啊   道道看题解

钦定1为根,DFS搜索子树权值。如果子树权值大于0就将当前节点加上子树权值,反之就把子树扔掉。最后在所有节点的权值中寻找最优解。

void dfs(int x,int fa){
    if(f[x]>0)    return;
    f[x]+=que[x];
    for(int i=head[x];i;i=edge[i].next){
        int to=edge[i].to;
        if(to==fa)    continue;
        dfs(to,x);
        if(f[to]>0)    f[x]+=f[to];
    }
    if(ans<f[x])    ans=f[x];
}

这就是DFS。第一行是个记忆化,如果f[x]已经被计算过返回。但我写错了……

然后 f[x]+=que[x]。因为f[x]是节点x及x子树的权值,如果不加上自己怎么行。

接下来是一个遍历,寻找自己所有的儿子节点。如果计算得出f[to]>0,那么说明这个子节点需要留着,因此f[x]+=f[to]

最后ans在所有f[x]中取得最优解。

代码如下

#include<cstdio>
#include<cctype>
inline long long read(){
    long long num=0,f=1;
    char ch=getchar();
    while(!isdigit(ch)){
        if(ch==‘-‘)    f=-1;
        ch=getchar();
    }
    while(isdigit(ch)){
        num=num*10+ch-‘0‘;
        ch=getchar();
    }
    return num*f;
}

struct Edge{
    int next,to;
}edge[1000000];
int head[1000000],num;
inline void add(int from,int to){
    edge[++num]=(Edge){head[from],to};
    head[from]=num;
}

int que[1000000];
int f[1000000];
int ans=-0x7fffffff;
void dfs(int x,int fa){
    if(f[x]>0)    return;
    f[x]+=que[x];
    for(int i=head[x];i;i=edge[i].next){
        int to=edge[i].to;
        if(to==fa)    continue;
        dfs(to,x);
        if(f[to]>0)    f[x]+=f[to];
    }
    if(ans<f[x])    ans=f[x];
}

int main(){
    int n=read();
    for(int i=1;i<=n;++i)    que[i]=read();
    for(int i=1;i<n;++i){
        int from=read(),to=read();
        add(from,to);
        add(to,from);
    }
    dfs(1,1);
    printf("%d",ans);
    return 0;
}
    
时间: 2024-08-11 15:23:25

【Luogu】P1122最大子树和(DFS,树上DP)的相关文章

[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)) (也就是一颗树的孩子所能取的子树,如果

P1122 最大子树和(树形dp)

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

Luogu P1122 最大子树和 树形DP

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

luogu P1122 最大子树和

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

洛谷P1122 最大子树和 树形DP

洛谷P1122 最大子树和一道类似树形DP 的题目 首先我们随意定根 ,假设我们定根为 1, 那么我们设dp[ i ] 表示 在这个整个以1为根的树中 以 i为根的子树 i 这个点强制取到 , 我们再从他的子树中取出一部分出来,最大能够取到的和 我们可知 当 枚举到dp[ u ] 时 ,我们看他的儿子取不取 如果v是它的儿子 若dp[ v ] > 0 那么我们就取 ,否则就不取,取了反而会减少 这样类似最长连续子序列一样就行了 然后类似树形DP 一样从根节点向根扩展就行了 ,也就是dfs下去 然

HZOJ 20190727 T2 单(树上dp+乱搞?+乱推式子?+dfs?)

考试T2,考试时想到了40pts解法,即对于求b数组,随便瞎搞一下就oxxk,求a的话,很明显的高斯消元,但考试时不会打+没开double挂成10pts(我真sb),感觉考试策略还是不够成熟,而且感觉考试时间很不够用,一直在瞎yy+code,听讲题DeepinC 12min就打出了T150pts,这不仅是思维上的劣势,而且打代码的速度必须要加上来啊,不然就算有好想法也打不出来(也没啥好想法). 接下来就是正经八本的题解了: 首先我们可以来一波玄学复杂度分析,数据范围1e5,要么$O(nlogn)

bzoj 2286 [Sdoi2011]消耗战(虚树+树上DP)

2286: [Sdoi2011]消耗战 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 1276  Solved: 445[Submit][Status][Discuss] Description 在一场战争中,战场由n个岛屿和n-1个桥梁组成,保证每两个岛屿间有且仅有一条路径可达.现在,我军已经侦查到敌军的总部在编号为1的岛屿,而且他们已经没有足够多的能源维系战斗,我军胜利在望.已知在其他k个岛屿上有丰富能源,为了防止敌军获取能源,我军的任务是炸

洛谷P1122 最大子树和

P1122 最大子树和 题目提供者该用户不存在 标签动态规划树形结构 难度普及/提高- 通过/提交54/100 提交该题 讨论 题解 记录 题目描述 小明对数学饱有兴趣,并且是个勤奋好学的学生,总是在课后留在教室向老师请教一些问题.一天他早晨骑车去上课,路上见到一个老伯正在修剪花花草草,顿时想到了一个有关修剪花卉的问题.于是当日课后,小明就向老师提出了这个问题: 一株奇怪的花卉,上面共连有N 朵花,共有N-1条枝干将花儿连在一起,并且未修剪时每朵花都不是孤立的.每朵花都有一个“美丽指数”,该数越

CodeForces 690C2 Brain Network (medium)(树上DP)

题意:给定一棵树中,让你计算它的直径,也就是两点间的最大距离. 析:就是一个树上DP,用两次BFS或都一次DFS就可以搞定.但两次的时间是一样的. 代码如下: #include<bits/stdc++.h> using namespace std; const int maxn = 1e5 + 5; vector<int> G[maxn]; int f[maxn], g[maxn], l[maxn]; int dfs(int root, int fa){ if(f[root] !=

Codeforces 453C Little Pony and Summer Sun Celebration dfs树上构造

题目链接:点击打开链接 题意: 给定一个无向图 任选一个起点,使得访问每个点的次数奇偶与最后一行的输入一致 思路: 选一个奇数点作为起点 dfs树一下,若子节点不满足则先走到子节点再回来 如此就能保证所有子节点合法 这样dfs结束后最多只有根节点不满足,随便找一个与根相连的点调整一下. #include <stdio.h> #include <string.h> #include <iostream> #include <math.h> #include &