HAOI2009 毛毛蟲 樹形DP

2022-04-30 00:42:26 字數 1780 閱讀 9391

題意:

給你一棵樹,從樹中取出一部分滿足:是一條鏈+一些直接連在這條鏈上的節點

求節點數最多的合法取出部分。

題解:

其實這題還是不難?

觀察到對於任意一條鏈,

只有兩種情況: 一條路走到底 or  以某個點為中轉

f[x]表示從x往下走,一路走到底的包括x的最優解,

f[x]包括x也包括father[x](將會加入它的貢獻)

觀察到以某個點為中轉的情況:

倘若某條鏈以乙個點為中轉,那麼這條鏈將無法向上產生貢獻,

若沒有,則變為第一種情況,且一定可以向上產生貢獻, 以點x為中轉的所有鏈都可以通過各個兒子的搭配得到

因此f[x]可以直接從f[son]中選取最優的來得到,

然後用f[x]來更新ans,

再選取兒子中的前2大,搭配起來加上x組成鏈,更新ans

所以dfs一遍然後輸出ans即可,複雜度o(n);

細節還是挺多的,要注意。

1 #include2

using

namespace

std;

3#define r register int

4#define ac 350000

5#define acway 700000

6#define getchar() *o++

7char read[10001000],*o=read;

8int

n,m,ans;

9int

in[ac],f[ac];

10int

date[acway],head[ac],next[acway],tot;

11/*

觀察到對於任意一條鏈,只有兩種情況:

12一條路走到底 :以某個點為中轉

13f[i]表示從i往下走,一條路走到底的最優解(不包括i)(非最長鏈)

14但這樣並不方便。。。。因為要分的情況太多,

15所以f[x]表示從x往下走,一路走到底的包括x的最優解,

16f[x]包括x也包括father[x]

17觀察到以某個點為中轉的情況:

18倘若某條鏈以乙個點為中轉,那麼這條鏈將無法向上產生貢獻,

19若沒有,則變為第一種情況。且一定可以向上產生貢獻,

20以點x為中轉的所有鏈都可以通過各個兒子的搭配得到,

*/21

22 inline int

read()

2329

30 inline void upmax(int &a,int

b)31

3435 inline void add(int f,int

w)36

4142

void

pre()

4351}52

53void dfs(int x,int

fa)54

68else

upmax(maxn2,f[now]);69}

70upmax(ans,f[x]);

71 upmax(ans,maxn + maxn2 + in[x] - 3);//

同上,只不過多減乙個兒子

72 }//

因為也會包括x,所以會重複2次

7374

void

work()

7580

81int

main()

82

HAOI2009 毛毛蟲 樹形dp

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

haoi2009 毛毛蟲 樹形dp

這道題細節處理不少,但要ac不難 設以i節點為根節點的子樹能形成的最大的毛毛蟲長度為f i 則f i max f j i節點的孩子數 答案需要f最大和次大的兩個子樹合併,而且若合併的位置不是根節點,ans 我就是坑在了最後一點上,最後打表找到了問題 1 include2 include3 inclu...

HAOI2009 毛毛蟲 樹的直徑

在一棵樹中,一條鏈及與它直接相連的所有邊的集合稱作乙個毛毛蟲,這個子圖中的點數稱作這個毛毛蟲的大小。求一棵樹中最大的毛毛蟲。n leq 3 times10 5 設每個點的權值為 deg i 1 然後求最長路即可,答案就是 ans 2 include using namespace std const...