NOIP/CSP 樹論題目口胡

我們假設你已經熟練掌握了樹上的各項基礎技術. 下面來做一下題吧!

1. [NOIP2007 提高組] 樹網的核

簡明題意:
給定一棵有 \(n\) 個結點的帶權無根樹, 在其直徑上找到一段長度不大於 \(s\) 的鏈 (稱爲核, 可退化爲一個點), 使得樹上的其他結點到該路徑距離的最大值 (稱爲偏心距) 最小.

我們發現原題裏數據範圍是 \(n\leqslant 300\), 但實際上我們可以做到 \(O(n)\).
大體思路就是, 我們隨便找一條直徑 \(D\), 然後在直徑上尺取.
具體地, 記直徑的端點分別爲 \(l\), \(r\), 選取的核 \(C\) 兩端分別爲\(x\), \(y\).
接下來我們計算偏心距 \(E\). 爲了方便表示, 記 \(d_u\) 爲從 \(u\) 到它不經過直徑能到達的最遠點的距離.
容易發現, 有 \(E=\max\{\max_{u\in C}\{d_u\},dis(l,x),dis(y,r)\}\).
(注意直徑是最長的鏈, 所以 \(x\) 所能到達的最遠點是 \(l\), \(y\) 所能到達的最遠點是 \(r\))
講道理現在就已經能用尺取做了.
但是注意到, 對於鏈 \((l,x)\) 上任意一點, 其 \(d\) 值不會大於 \(dis(l,x)\). (\((y,r)\) 的情況同理)
則原式化簡爲 \(E=\max\{\max_{u\in D}\{d_u\},dis(l,x),dis(y,r)\}\).
此時 \(\max_{u\in D}\{d_u\}\) 這一項可以預處理出來, 不用在尺取中維護了.
最終我們就以 \(O(n)\) 的時間複雜度解決了這道題.

2. [NOIP2018 提高組] 賽道修建

簡明題意:
給定一棵有 \(n\) 個結點的帶權無根樹, 現在要用 \(m\) 條路徑來覆蓋一些邊, 且一條邊不能被覆蓋兩次. 求長度最小的路徑長度的最大值.

最小值最大, 不難想到要二分這個最小值. 然後就發現不好做了.
考慮部分分. 出題人非常良心, 給了我們一些提示.

  • \(m=1\). 顯然取直徑.
  • 鏈. 這就很典了, 貪心選擇即可.

上面的部分分非常基礎, 但也高達 40 分了(
進入正題.

  • 菊花圖.
    注意每次只會取一條或兩條邊, 我們設當前二分的值爲 \(mid\), 對大於等於 \(mid\) 和小於 \(mid\) 的邊分開考慮.
    小於 \(mid\) 的邊儘量配對, 這個雙指針就能做. 餘下的邊和大於等於 \(mid\) 的邊配對.
    如果還有小於 \(mid\) 的邊說明不成立, 如果還有大於等於 \(mid\) 的邊兩兩配對即可.

  • 每個點的度數 \(\leqslant3\).
    這個部分分就非常接近正解了. 首先我們隨便欽定一個點作爲根.
    爲方便描述, 我們稱一條鏈 \((u,v)\) 是直鏈當且僅當 \(u\)\(v\) 的祖先或 \(v\)\(u\) 的祖先.
    然後我們記 \(l_u\) 爲使得答案最優的從 \(u\) 開始向下的直鏈長度. (有點抽象)
    我們考慮將一條鏈在端點的 LCA 處拆成兩條直鏈. 這樣我們只需要先統計直鏈, 然後兩兩合併即可.
    因爲每個點的度數不超過 \(3\), 所以當前點最多有兩個兒子. 分類討論:

    • 並沒有兒子: 顯然 \(l_u=0\).
    • 只有一個兒子 \(v\):
      • \(l_v\geqslant mid\): 題目並沒有說兩條鏈不能佔用相同頂點, 於是我們直接令 \(l_u=dis(u,v)\).
      • 否則令 \(l_u=l_v+dis(u,v)\), 若 \(l_u\geqslant mid\) 則計入答案, 否則不計.
    • 有兩個兒子:
      • 如果有兒子滿足 \(l_v\geqslant mid\), 那我們可以無視下面的直鏈, 而用 \(dis(u,v)\) 代替 \(l_v\) 參與 \(l_u\) 的計算.
      • 如果有兒子滿足 \(l_v+dis(u,v)\geqslant mid\), 我們將這條鏈計入答案, 然後無視它.
      • 如果只有一個兒子 滿足 \(l_v+dis(u,v)<mid\), 那我們令 \(l_u=l_v+dis(u,v)\).
      • 如果兩個兒子都有 \(l_v+dis(u,v)<mid\), 那我們先嚐試將兩條鏈合併.
        • 如果兩條鏈合併長度 \(\geqslant mid\), 那麼將這條合併出的鏈計入答案, 並且令 \(l_u=0\).
        • 否則選 \(l_v+dis(u,v)\) 大的作爲 \(l_u\).

部分分終於說完了. 正解就是將菊花圖和度數 \(\leqslant3\) 的方法合起來.
我們考慮度數大於 \(3\) 的時候怎麼合併.
顯然對於加上 \(dis(u,v)\) 鏈長還小於 \(mid\) 的直鏈使用雙指針進行合併就行. 在餘下的直鏈中取一條最大的作爲 \(l_u\).

然後就做完了(

3. [NOIP2015 提高組] 運輸計劃

簡明題意: 給一棵 \(n\) 個點的帶權無根樹和 \(m\) 條鏈, 現在要將樹上的一條邊的權值改爲 \(0\), 要求使修改後鏈的長度的最大值最小.

首先枚舉改哪條邊是沒有出路的! 樹剖/LCT \(O(nm\log^2n)/O(nm\log n)\) 就很難再優化了.
考慮二分答案, 所以說應該怎麼判定?
記當前二分到的答案爲 \(mid\).
首先我們找出來所有長度超過 \(mid\) 的鏈. 鏈的長度可以隨手預處理掉.
然後我們只需要找出來這些鏈的交, 這個可以用樹上差分維護.
最後在交出的鏈上枚舉改哪條邊的權值即可.

4. [NOIP2012 提高組] 疫情控制

題意:
給定一棵 \(n\) 個點的帶權有根樹, 樹根爲 \(1\).
現在一些點上有棋子, 共有 \(m\) 枚棋子, 且一個點上可以有多枚棋子.
現在要移動棋子, 使根到任意一個葉子的路徑上都有至少一枚棋子. 注意棋子最終不能放到根上.
求移動距離最長的棋子經過的路徑長度.

考慮二分這個最長的路徑長度. 然後我們就可以讓每個棋子在這個長度範圍內爲所欲爲了!

很明顯每個棋子都應該儘可能向根靠近. 我們可以直接讓每個棋子儘可能向上跳. 這一步可以通過倍增預處理出向上的路徑長度簡單求出. 注意跳到根的子節點就不要再往上了.
經過這一步我們就會得到兩類棋子, 無法再上提的棋子和能夠繞過根結點到達另一棵子樹的棋子.
顯然能夠繞過根結點到另一棵子樹的棋子都分佈在根結點的子節點上.

下一步, 我們找出所有沒有被封上的根結點的子樹, 然後考慮將能繞過根結點的棋子放到子樹的根上封上這些路徑. 顯然讓剩餘路程大的棋子去離根結點距離大的子樹就行了.

到此就做完了. 思路並不難想到, 但是寫起來並不簡單.

5. [NOIP2016 提高組] 天天愛跑步

簡明題意: 給一棵無權樹, 每個點有一個點權 \(w_p\). 給定一些有向路徑 \((u_k,v_k)\).
對於每個結點 \(p\), 求出滿足 \(p\)\((u_k,v_k)\) 上且 \(dis(u_k,p)=w_p\)\((u_k,v_k)\) 的數量, 其中 \(dis(u,v)\)\(u,v\) 間的路徑長度.

6. [NOIP2018 提高組] 保衛王國

簡明題意: 求帶點權的樹的最小點覆蓋, 但是每次會指定兩個點 \(a,b\), 要求必須/不能選 \(a\), 必須/不能選 \(b\).

衆所周知最小點覆蓋 \(=n-\) 最大獨立集, 必須/不能選就是將點權更改爲 \(\infty\)\(-\infty\). 然後上 ddp 板子, 時間複雜度 \(O(n\log n+q\log^2 n)/O((n+q)\log n)\).

7. [NOIP2018 提高組] 旅行 加強版

簡明題意: 在一棵樹或基環樹上跑 dfs, 求字典序最小的 dfs 序.

一堆樹論題目中混入了一棵基環樹(
首先 \(m=n-1\) 即樹的情況是顯然的. 貪心 dfs 即可.
然後我們考慮 \(m=n\) 的基環樹.
原題直接暴力刪環上的邊就能過, 但是加強版讓我們需要想出一個 \(O(n\log n)\) 的算法.
顯然我們只需要討論走到環上的時候怎麼決策.
設我們現在走到了環上的點 \(u\), 下一步能走到的點爲 \(u',v_1,\cdots, v_s\), 其中 \(u'\) 是環上的點.
另外我們記當前回溯能走到的點是 \(p\).
分類討論:

  • \(u'\) 是下一步能走到的點中最小的, 那麼當然要先走 \(u'\).
  • \(\exist v_k>u'\), 則我們也是要走完 \(u'\) 之後才能走 \(v_k\).
  • \(\forall v_k, v_k<u'\), 則我們要先走完所有的 \(v_k\). 然後下面又有兩種情況:
    • \(u'<p\): 正常先走 \(u'\).
    • \(u'>p\): 手動回溯, 先走 \(p\).
    • 注意我們只有一次手動回溯的機會, 之後對於上面兩種情況都是先走 \(u'\).

做完了. 複雜度瓶頸在於排序.

8. [CSP-S2019] 樹的重心

一句話題意: 求出無權樹 單獨刪去每條邊 得到的兩個子樹的重心編號和 的和.

9. [CSP-S2019] 樹上的數

大 思 維 題.

題意:
有一棵樹, 結點編號爲 \(1,2,\cdots, n\), 每個結點上有一個 \([1,n]\) 內的整數, 且每個結點上的數互不相同.
每次可以選擇一條邊, 使這兩個結點上的數交換. 現要對每條邊進行且只進行一次操作.
試確定操作順序使所有操作完成後, 將結點按照上面的數字進行排序時, 結點編號排列的字典序最小.

直接做是困難的, 考慮部分分.

  • 菊花圖.
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章