藍橋杯 生命之樹 樹狀dp

2022-07-31 08:21:13 字數 1269 閱讀 6176

在x森林裡,上帝建立了生命之樹。

他給每棵樹的每個節點(葉子也稱為乙個節點)上,

都標了乙個整數,代表這個點的和諧值。

上帝要在這棵樹內選出乙個非空節點集s,

使得對於s中的任意兩個點a,b,都存在乙個點列

使得這個點列中的每個點都是s裡面的元素,且序列中相鄰兩個點間有一條邊相連。

在這個前提下,上帝要使得s中的點所對應的整數的和盡量大。

這個最大的和就是上帝給生命之樹的評分。

經過atm的努力,他已經知道了上帝給每棵樹上每個節點上的整數。

但是由於 atm 不擅長計算,他不知道怎樣有效的求評分。

他需要你為他寫乙個程式來計算一棵樹的分數。第一行乙個整數 n 表示這棵樹有 n 個節點。

第二行 n 個整數,依次表示每個節點的評分。

接下來 n-1 行,每行 2 個整數 u, v,表示存在一條 u 到 v 的邊。

由於這是一棵樹,所以是不存在環的。輸出一行乙個數,表示上帝給這棵樹的分數。5

1 -2 -3 4 5

4 23 1

1 22 58這是一道樹狀dp題,每個節點只有兩種決策,選與不選,因此我們建立乙個陣列。

int dp [ n ][2] ;其中,dp[ i ][ 1 ]表示選第i個節點的情況下最大分數,dp [ i ][ 0 ]為不選的情況下的最大分數。

d[ i ][ 0 ] = t,那麼存在乙個 i 的子節點 j,使得 d[ j ][ 1 ] 的值也為 t , 因此我們可以讓所有的d[ i ] [ 0] = 0

這樣一來,狀態轉移方程很容易寫出來:

\[}[i][1] = \sum   + w[i]\]

\[}[i][1] = \sum })}  + w[i]\]

其實這樣子,大家就能發現,dp[i][0]沒有用到,dp設成一維的,也是可以解決這個問題的。

#include#include#include#includeusing

namespace std;

int w[100005];

int vist[100005];

int dp[100005];

int n;

int ans = -0x3f3f3f3f;

vector g[100005];

void dfs(int u)

} ans = max(dp[u], ans);

}int main()

dfs(1);

cout << ans << endl;

return 0;

}

藍橋杯2015初賽 生命之樹(樹狀dp)

在x森林裡,上帝建立了生命之樹。他給每棵樹的每個節點 葉子也稱為乙個節點 上,都標了乙個整數,代表這個點的和諧值。上帝要在這棵樹內選出乙個非空節點集s,使得對於s中的任意兩個點a,b,都存在乙個點列 使得這個點列中的每個點都是s裡面的元素,且序列中相鄰兩個點間有一條邊相連。在這個前提下,上帝要使得s...

藍橋杯 生命之樹 樹形DP

生命之樹 在x森林裡,上帝建立了生命之樹。他給每棵樹的每個節點 葉子也稱為乙個節點 上,都標了乙個整數,代表這個點的和諧值。上帝要在這棵樹內選出乙個非空節點集s,使得對於s中的任意兩個點a,b,都存在乙個點列 使得這個點列中的每個點都是s裡面的元素,且序列中相鄰兩個點間有一條邊相連。在這個前提下,上...

藍橋杯 生命之樹 樹形dp

在x森林裡,上帝建立了生命之樹。他給每棵樹的每個節點 葉子也稱為乙個節點 上,都標了乙個整數,代表這個點的和諧值。上帝要在這棵樹內選出乙個非空節點集s,使得對於s中的任意兩個點a,b,都存在乙個點列 使得這個點列中的每個點都是s裡面的元素,且序列中相鄰兩個點間有一條邊相連。在這個前提下,上帝要使得s...