題目傳送門
對於一棵樹,我們可以將某條鏈和與該鏈相連的邊抽出來,看上去就象成乙個毛毛蟲,點數越多,毛毛蟲就越大。例如下圖左邊的樹(圖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 將會加入...