NOIP樹上問題總結


這幾年考了好幾次樹上問題:

NOIP2012 疫情控制(二分答案+倍增+貪心)

NOIP2013 貨車運輸(最大生成樹+倍增)

NOIP2014 聯合權值(勉強算作樹形dp的傻逼題)

NOIP2015 運輸計划(二分答案+樹上差分+最近公共祖先)

NOIP2016 天天愛跑步(樹上差分+樹上倍增)

可以說除了聯合權值外都有一定的難度,(關鍵是我不抄題解一道也做不出來)

去年沒考樹上的問題所以我感覺今年要考

樹是一種極其優美的結構,樹上兩點之間有且僅有一條路徑。

在近年來oi中常出現關於樹的題目。

樹的直徑

樹的直徑就是樹中最長的一條路徑,處理方法有樹形dp和兩遍dfs或bfs

需要注意的是在存在負邊權的樹中只能用樹形dp來求直徑

1.巡邏

一道畫畫圖就能搞出來的題。。。

首先我們應該想想他讓我們修路有什么用。你隨便畫一棵樹就很容易發現,要想從一個點出發經過所有點一遍再回來,每條邊是要經過兩次的。而我們修路就是為了讓其中一些邊只走一次。

$K=1$:顯然我們隨意連一條邊會形成一個環,環上的邊我們只用經過一次。這樣我們最大化環的的長度就行,也就是找到樹的直徑。

$K=2$:首先我們肯定還是連直徑。但是第二條邊怎么連?顯然我們還可以找次長鏈出來。但如果兩條鏈有重疊怎么辦?

我們可以把第一條鏈在算完長度后將所有邊權賦成-1,這樣就不會算重了。設兩次選的邊長度分別為$l1$,$l2$,那么答案就是$2*n-l1-l2$。

2.消防

首先我們應該想到這條路徑一定在樹的直徑上。這里給出證明:

設直徑的長度為$d$,那么直徑外的邊長度一定小於等於$d/2$(否則該路徑會與直徑的一部分構成一條比直徑還長的路徑)

若該路徑不在直徑上,則直徑的最遠點到該路徑的距離至少為$d/2$

而如果在直徑上,一定存在一段路徑使得樹上所有點的距離到它不超過$d/2$

所以選在直徑上一定是優的,而且在符合題目要求的情況下越長越好。

那么如果我們確定里直徑,我們可以$O(n)$求出直徑上每個點到最遠點的距離,然后左右指針掃直徑,單調隊列維護區間最小值即可。

3.直徑

求直徑的長和直徑並的數量。

直徑當然好求,而直徑並,一定是在一條直徑上。

所以我們可以先求出一條最長鏈。而所有直徑的並一定是最長鏈上連續的一段。

證明很簡單:如果中間有分開而最后又和在一起,顯然會形成一個環。

然后我們對於最長鏈上的每個點,dfs求出其子樹中距離最遠的點,若兩點之間的距離等於該點到直徑一個端點的距離,那么顯然這個點到端點之間這一段就不能用來統計答案了,將它們從答案中刪除即可。

然后我們可以正着做一遍這個操作,反向再做一遍,中間沒被刪除部分即為直徑的並

 樹上管理問題

樹上的每個點能管理相鄰一片區域,求最少幾個點能管理整棵樹。

一般考慮從下往上貪心。

1.救火站Gas

又是樹上管理類的問題,我們當然考慮貪心。這個題算是消防站的設立那道題的加強版。

很顯然的一種做法是對於一個點,我們要找一個深度最小的點來覆蓋它。

然后看這個數據范圍$k<=20$,我們可以想到把他當成狀態放進數組里

設$need[i][j]$為以$i$為子樹的$j$級子孫有幾個未覆蓋,$left[i][j]$為以$i$為子樹的$j$級子孫有幾個多出來控制的沒使用

顯然當$need[i][j]$中$j=k$時,我們就必須放消防站來管理了

然后我們還可以用$left$來抵消$need$

2.消防局的設立

有一種很顯然的貪心測略:對於當前深度最大的點,我們選他的爺爺點一定是最優的。

對於最深的點我們選離他最遠但是能管理到他的祖先即可。

樹上倍增&&樹上差分

這幾年考過好幾次樹上倍增,有兩次都是和樹上差分結合在一起的。利用樹上倍增求出兩點的$LCA$,然后兩點$(u,v)$之間邊的信息往往可以轉化為$(u->root)+(v->root)-2*(LCA->root)$,點的信息可以轉化為$(u->root)+(v->root)-LCA->root-fa_LCA->root$。

1.天天愛跑步

對於每一條鏈,我們根據套路把他拆成$(u->root)+(v->root)-LCA->root-fa_LCA->root$

然后我們發現$(u->root)$和$(v->root)$要分別處理(因為一個往上走一個往下走)

設觀察員$y$出現的時間為$w_y$

那么$x$向上跑要想被觀察員看見,就要滿足等式$deep_x-w_y=deep_y$,移項得到$deep_x=deep_y+w_y$,換句話說,$y$子樹內只有滿足$deep_x=deep_y+w_y$的點會對$y$產生貢獻

當$x$向下跑想被$y$看見,我們可以設$x$的時間為$ed_x$,根據剛才的套路,我們發現子樹內只有滿足$deep_x-ed_x=deep_y-ed_y$的點會對$y$產生貢獻

用一個桶dfs一遍即可求出答案,是不是越想越簡單了。。

2.運輸計划

根據套路最大值最小的問題我們考慮二分,假設我們二分出來的答案為$mid$,那么我們顯然要把大於$mid$的所有計划減去同一條邊,且這條邊在大於$mid$的計划的路徑並上

我們差分一下求出每個計划對路徑的覆蓋,只有覆蓋數目等於大於$mid$的計划的邊可以考慮被減去

對這些可以減去的邊取一個最大值然后判斷即可

以前感覺這道題很神仙,其實仔細一分析每一步都是套路

3.疫情控制

 仔細分析題目,好像還是最大值最小啊,當然是考慮二分咯。顯然我們在軍隊沒跳到首都之下的兒子上時,一直往上跳是最優的

但調到首都兒子上時,我們發現一個問題,如果接着往上跳,很可能在這個點重新需要控制的時候就跳不回來了,那還不如不跳

所以我們把所有調到首都后能返回他上一個兒子的點全部跳到首都,對於子樹內的所有葉子已經被覆蓋的軍隊當然也跳到首都,因為再留在這個點已經沒有意義了

然后我們在首都枚舉所有的葉子,如果還沒被覆蓋,就從首都派遣軍隊進行覆蓋,如果所有軍隊都到不了葉子的祖宗,自然二分的答案不合法


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM