樹形dp 題解 洛谷P3174 毛毛蟲

2021-09-16 13:58:02 字數 1850 閱讀 9297

題目傳送門

對於一棵樹,我們可以將某條鏈和與該鏈相連的邊抽出來,看上去就象成乙個毛毛蟲,點數越多,毛毛蟲就越大。例如下圖左邊的樹(圖1)抽出一部分就變成了右邊的乙個毛毛蟲了(圖2)。

輸入格式

第一行兩個整數n,m,分別表示樹中結點個數和樹的邊數。

接下來m行,每行兩個整數a, b表示點a和點 b有邊連線(a, b≤n)。你可以假定沒有一對相同的(a, b)會出現一次以上。

輸出格式

乙個整數, 表示最大的毛毛蟲的大小。

題目可以轉化為讓你求乙個鏈,這條鏈所包含的節點個數最多。

對於乙個節點x,我們設dp

[x]是

以x為根

節點的最

大節點數

設dp[x]是以x為根節點的最大節點數

設dp[x]

是以x為

根節點的

最大節點

數 我們通過枚舉子節點y來更新x

不難發現,對於每乙個x,y至多只能選乙個,而其他的子節點也都要算進去,因為直接與他相連。

設 nu

m[x]

表示x所

相連的點

的個數設num[x]表示x所相連的點的個數

設num[x

]表示x

所相連的

點的個數

那麼我們就可以得到以下算式:

d p[

x]=m

ax(d

p[y]

+num

[x]−

1)(y

∈son

(x))

dp[x]=max(dp[y]+num[x]-1)\ (y\in son(x))

dp[x]=

max(

dp[y

]+nu

m[x]

−1)(

y∈so

n(x)

)那麼dp的方程求好了,考慮如何求出答案。

不難發現,最後的答案其實就是最長鏈

與次長鏈

之和,再

加上節點

的個數−

1最長鏈與次長鏈之和,再加上節點的個數-1

最長鏈與次長

鏈之和,

再加上節

點的個數

−1。我們只需要在dp時更新答案即可。

#include

using

namespace std;

struct nodee[

700000];

int linkk[

700000];

int sum[

700000];

int num[

700000];

int dp[

700000];

int n,m,len=0;

//int maxx1;

//int maxx2;

int ma***=0;

void

insert

(int x,

int y)

void

find_sum

(int x,

int fa)

}void

treedp

(int x,

int fa)

ma***=

max(ma***,maxx1+maxx2+num[x]-1

);//更新

}int

main()

P3174 HAOI2009 毛毛蟲 題解

同步 原題鏈結 簡要題意 給定一棵樹,求最長的 掛鏈 長度。掛鏈定義為 一條鏈上所有節點與其相連的節點構成的生成樹。非嚴謹定義 原題中是 毛毛蟲 本人以為掛鏈更形象 這題有多種做法,這裡給出思路,以及其中一種做法的 注意到,其實我們只需要選出 最長鏈 然後在最長鏈的兩側掛鏈即可。即,先求出樹的直徑的...

HAOI2009 毛毛蟲 樹形dp

試題描述 對於一棵樹,我們可以將某條鏈和與該鏈相連的邊抽出來,看上去就象成乙個毛毛蟲,點數越多,毛毛蟲就越大。例如下圖左邊的樹 圖 1 抽出一部分就變成了右邊的乙個毛毛蟲了 圖 2 輸入資料 在文字檔案 worm.in 中第一行兩個整數 n m 分別表示樹中結點個數和樹的邊數。接下來 m 行,每行兩...

HAOI2009 毛毛蟲 樹形DP

題意 給你一棵樹,從樹中取出一部分滿足 是一條鏈 一些直接連在這條鏈上的節點 求節點數最多的合法取出部分。題解 其實這題還是不難?觀察到對於任意一條鏈,只有兩種情況 一條路走到底 or 以某個點為中轉 f x 表示從x往下走,一路走到底的包括x的最優解,f x 包括x也包括father x 將會加入...