最大子樹和

2022-08-19 05:45:14 字數 1701 閱讀 5202

題目描述

小明對數學飽有興趣,並且是個勤奮好學的學生,總是在課後留在教室向老師請教一些問題。一天他早晨騎車去上課,路上見到乙個老伯正在修剪花花草草,頓時想到了乙個有關修剪花卉的問題。於是當日課後,小明就向老師提出了這個問題:

一株奇怪的花卉,上面共連有n 朵花,共有n-1條枝幹將花兒連在一起,並且未修剪時每朵花都不是孤立的。每朵花都有乙個「美麗指數」,該數越大說明這朵花越漂亮,也有「美麗指數」為負數的,說明這朵花看著都讓人噁心。所謂「修剪」,意為:去掉其中的一條枝條,這樣一株花就成了兩株,扔掉其中一株。經過一系列「修剪「之後,還剩下最後一株花(也可能是一朵)。老師的任務就是:通過一系列「修剪」(也可以什麼「修剪」都不進行),使剩下的那株(那朵)花卉上所有花朵的「美麗指數」之和最大。

老師想了一會兒,給出了正解。小明見問題被輕易攻破,相當不爽,於是又拿來問你。

輸入輸出格式

輸入格式:

輸入檔案maxsum3.in的第一行乙個整數n(1 ≤ n ≤ 16000)。表示原始的那株花卉上共n 朵花。

第二行有n 個整數,第i個整數表示第i朵花的美麗指數。

接下來n-1行每行兩個整數a,b,表示存在一條連線第a 朵花和第b朵花的枝條。

輸出格式:

輸出檔案maxsum3.out僅包括乙個數,表示一系列「修剪」之後所能得到的「美麗指數」之和的最大值。保證絕對值不超過2147483647。

輸入輸出樣例

輸入樣例#1: 複製

7-1 -1 -1 1 1 1 0

1 42 5

3 64 7

5 76 7

輸出樣例#13說明

【資料規模與約定】

對於60%的資料,有n≤1000;

對於100%的資料,有n≤16000。

懶得寫,拷乙份

這道題有一種最大子段和的感覺,因為沒有確定的樹根,所以最大的子樹和可以作為其中任意的一段。

最大子段和的o(n)o(n)o(n)求法非常巧妙,方法就是從頭記錄乙個子段和,當這個和小於0的時候,顯而易見,這個子段對答案就沒有貢獻了,這個思想同樣也可以運用到這個題目中

我們設f[i]f[i]f[i]表示這個點的最大子樹的和,那麼就可以用dfs求出它的兒子節點的子樹的和,我們就只選取大於0的子樹。

所以方程可以這麼寫f[i]+=dfs(i.son)[dfs(i.son)>0]f[i]+=dfs(i.son)[dfs(i.son)>0]f[i]+=dfs(i.son)[dfs(i.son)>0]初始化就是f[i]=a[i]f[i]=a[i]f[i]=a[i]

程式就非常好寫了,細節上注意不要讓兒子搜到自己的父親就可以。

#include#include#include#include#include#includeusing namespace std;

typedef long long ll;

const int maxn = 20000;

vectorg[maxn];

int n;

int f[maxn];

int vis[maxn];

int dfs(int x)

} return f[x];

}int main()

dfs(1);

int ans = -1;

for(int i = 1;i <= n;i++)

ans = max(ans,f[i]);

cout

}

尋找最大子樹

問題描述 給乙個二叉樹,每個節點都是正或負整數,如何找到乙個子樹,它所有節點的和最大?思路 採用自底向上的計算。先計算左右子樹總和值,用左右子樹的總和加上當前節點值,如果當前總和大於最大值,則更新最大值,同時將最大子樹根節點更新為當前根。簡單說,就是後序遍歷。include include usin...

模版 最大子樹和 題解

樹上dp 給出一棵樹,上面有權值,求這個數的子樹的最大權值和。模板題,就是樹上dp。可以想到只要這個樹的子樹的權值大於0就可以選擇,即加上這個權值。所以這個dp的轉移方程是 f i sum nf 0 其中 n 表示這個子樹大小,a i 表示這個子樹的子節點。include using i64 lon...

P1122 最大子樹和

小明對數學飽有興趣,並且是個勤奮好學的學生,總是在課後留在教室向老師請教一些問題。一天他早晨騎車去上課,路上見到乙個老伯正在修剪花花草草,頓時想到了乙個有關修剪花卉的問題。於是當日課後,小明就向老師提出了這個問題 一株奇怪的花卉,上面共連有nn朵花,共有n 1n 1條枝幹將花兒連在一起,並且未修剪時...