傳送門:qaqqaq
題意:給你一棵樹,每個點有權值,把樹上$n$個點分成若干個集合,每個集合中的元素兩兩之間不存在祖先關係,使得每個集合中的最大值之和最小
思路:觀察部分分,我們會發現有乙個「鏈」的樣例。我們看鏈的思路:1為頂點,那麼1兩端就是兩條鏈,每個集合中每條鏈只能包含1個元素,然後1頂點單獨拿出來,那麼我們就兩條鏈的最大值乙個個取出來作為乙個個集合,那麼最終的就是最優解
推廣:如果以1為頂點有多條鏈,那麼可以在每條鏈上維護乙個堆,每次取堆中的最大值合併$ans$加上合併後的最大值就可以了
再推廣:我們看一般的樹,如果一顆子樹的頂點下是多條鏈,那麼我們可以按照上述方法把多條鏈合成一條鏈(把鏈短的連到長的)因為最底層一定是多鏈,所以這樣遞迴上去時一定保證每個頂點處理時下面一定是多條鏈
在**實現方面,會有乙個swap兩個堆的操作,我們如果直接swap會mle,所以我們用乙個$id[x]$表示頂點$x$所對應的堆的編號,那麼在交換堆的時候直接交換$id$就可以了
#includeusingnamespace
std;
typedef
long
long
ll;const
int inf=(int
)(2e9);
const ll inf=(ll)(5e18);
const
int n=200010
;vector
v[n];
inta[n],n,id[n];
ll ans=0
;priority_queue
q[n];
vector
q;void dfs(int
u)
while
(q.size()) q[id[u]].push(q.back()),q.pop_back();
}q[id[u]].push(a[u]);
}int
main()
dfs(1);
while(!q[id[1]].empty()) ans+=q[id[1]].top(),q[id[1
]].pop();
cout
return0;
}
P5290 十二省聯考2019 春節十二響
傳送門 考慮乙個子樹裡是怎麼劃分的,維護劃分出來的每個集合的最大值,這個可以用乙個 multiset 維護 設 s x 表示節點 x 的子樹中,最優劃分 劃分出來的每個塊的節點最大值 首先葉子節點的集合顯然只有它本身 然後考慮子樹之間的合併,設兩個子樹根節點為 x,y 因為兩個子樹之間一定不會有祖先...
P5290 十二省聯考2019 春節十二響
考試的時候,本來想拿60的貪心,但是只拿了15 很不開心!不過現在知道正解了qwq 對於每個點,都開乙個優先佇列,這個優先佇列裡的值,代表這個點的子樹分成的若干個集合中最大的值。那麼我們對於乙個沒有處理的點,分別列舉每乙個子樹,分別合併每乙個優先佇列,最後再加入這個點,得到新的優先佇列。對於正確性,...
洛谷P5049 洛谷P5022 題解 旅行
原題 資料加強版 加強版 參考你谷題解 終於調過了 又是一如既往的申必錯誤 noi plus石錘了 原題的資料允許我們 o n 2 暴力斷邊,但是加強版的資料達到了 n log n 級別,我們必須在斷邊這一環節尋求更好的解法。考慮我們進入環後在何處回溯 根據繼續走環走到的點分類 設當前已經從 b 走...