N 城市,N-1 條邊構成樹。K 個城市有機器。需刪除一些邊使任意兩機器城市不連通,每條邊刪除需時 z,一次只能刪一條,求最小總時間(即所需刪除邊權值之和)。
樹上任意兩點唯一路徑。要分離所有機器城市,必須刪除連接不同機器所在連通分量的邊。將每個機器城市視為一個集合,從大到小考慮邊:若一條邊連接兩個都含有機器的集合,則必須刪除它(權值計入答案),並合併集合;否則合併集合但不計入答案。這正是克魯斯克爾最大生成樹的變體。
hasMachine[root]=true。u=find(x), v=find(y)。若 u!=v:hasMachine[u] && hasMachine[v] → ans += w;hasMachine[newRoot] = hasMachine[u] || hasMachine[v]。struct Edge { int u, v; long long w; };
bool cmp(Edge a, Edge b) { return a.w > b.w; }
int find(int x) { return f[x]==x?x:f[x]=find(f[x]); }
int main() {
int T; scanf("%d", &T);
while (T--) {
int N, K; scanf("%d%d", &N, &K);
vector edges(N-1);
for (int i=0; i
排序 O(N log N),並查集 O(N α(N)),總體 O(N log N),N≤100,000 極快。