你爲何要讀這篇文章(本文涉及的內容):本題(包括加強版)的算法的詳細描述與貪心的正確性證實。算法
2020-03-12 edit:優化
偶然翻到這篇博文,感受本身寫的題解是真的太毒瘤了……連我本身都看不懂本身寫了啥。spa
作了一點修改與補充,enjoy!排序
二分答案+貪心。部署
下文中,咱們:get
考慮\(leaf(u)\)被控制的充分必要條件:it
爲了簡化問題,咱們先考慮在二分到\(mid\)時,哪些軍隊的位置是固定的。io
顯然,對於那些「不能到達根節點」,即\(d(x,1)>mid\)的軍隊\(x\),儘可能向上移動是最優的。class
那麼,能夠用倍增在\(O(\log n)\)時間內處理出這些軍隊的最終位置,能夠經過 DFS 求出根的哪些兒子的子樹(的葉節點)沒有被(徹底)控制,設其集合爲\(S_1\subseteq son(1)\)。(顯然,其餘節點都部署在根的兒子上)方法
以後,就是考慮可以到達根\(1\)的節點如何部署的問題了。因爲離根越遠的兒子越難知足,根據貪心的原則,優先考慮離根最遠的兒子\(u\):
一個實現上的優化:若\(u\)的子樹內能夠到達\(u\)且離\(u\)最遠的軍隊已經被部署,則\(u\)的子樹內已經沒有未被部署的軍隊(由於老是由近到遠選擇軍隊部署),直接轉到2便可。
若某個可行解裏\(x\)部署到了\(v\in S_1,v\ne u\)上(或者沒有部署,此時正確性是顯然的),考慮該解中,部署在\(u\)的軍隊\(x'\),則其能夠與\(x\)交換部署的位置。咱們來證實這一點。
有假設,顯然有\(d(x',u)\le mid,d(x,v)\le mid\)。此外,\(x\)必定能夠部署到\(u\)上,有\(d(x,u)\le mid\)。
故咱們只須要說明\(x'\)能夠部署在\(v\)上,即\(d(x',v)\le mid\)便可。咱們來分狀況說明這一點:
如下的證實爲了避免把行內公式寫得太長,跳過了一些步驟。
具體證實最多隻需用到\(d(x,y)\le d(x,z)+d(z,w)\),就做爲留給讀者的練習了~
那麼(基本上只須要按照上面的描述)直接寫就能夠了。(注意細節……這題畢竟是個紫題……)
增強版的數據要求算法複雜度只能一個\(\log\),怎麼辦?
顯然,二分答案這一步是沒辦法去掉的……只能嘗試把判斷可行性優化到\(O(n)\)。
注意到在\(mid\)時間內處理出(不)能夠到\(1\)的軍隊是簡單的:預先處理出全部\(d(x,1)\)並排序,則答案爲一個它的一個前綴。
考慮不倍增怎麼求\(1\)的「哪些\(u\in son(v)\)的子樹被控制」。換句話說,對於一個節點\(u\in son(1)\),咱們須要知道:
標記那些\(d(x,1)>mid\)的軍隊\(x\)(在樹上的位置),在 DFS 到\(u\)時顯然能夠全部\(v\in son(u)\)的子樹是否被控制,以及節點\(u\)距離最近的\(x\in tree(u)\)的距離,判斷是否有\(d(x,u)\le mid\)便可。
LOJ最短代碼 (寫文章時)