n 個部件(節點),m 條繩子(無向邊)。v[i]。(u,v) 的代價 = min(v[u], v[v])。無論刪除順序,每條邊最終都會被剪斷,代價固定為兩端點權值的較小者。
總代價 = ∑_{edge (u,v)} min(v[u], v[v]) —— 與順序無關!
u 時,其所有 尚未移除的鄰居 v 必滿足 v[v] ≤ v[u]。(u,v) 的代價即為 v[v](較小者)。v[v] 即得答案。此過程等價於:對每條邊,由權值較大的端點「貢獻」較小權值。
n, m 及 v[1..n]。g[u]。id[1..n],按 v[id[i]] 降序排序。vis[u] = false 初始化。u:vis[u] = trueto:若 !vis[to] 則 ans += v[to]。ans。#include <bits/stdc++.h>
using namespace std;
const int N = 1005;
int n, m, val[N];
vector<int> g[N];
int idx[N];
bool vis[N];
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
if (!(cin >> n >> m)) return 0;
for (int i = 1; i <= n; ++i) {
cin >> val[i];
idx[i] = i;
}
sort(idx + 1, idx + n + 1, [&](int a, int b) {
return val[a] > val[b];
});
for (int i = 0; i < m; ++i) {
int u, v; cin >> u >> v;
g[u].push_back(v);
g[v].push_back(u);
}
long long ans = 0;
for (int i = 1; i <= n; ++i) {
int u = idx[i];
vis[u] = true;
for (int v : g[u]) {
if (!vis[v]) ans += val[v];
}
}
cout << ans << '\n';
return 0;
}
O(n log n)O(m)O(n log n + m),n ≤ 1000, m ≤ 2000 極輕鬆。O(n + m)。雖然總代價與順序無關,但「按權值從大到小處理」提供了一種 構造性證明:
當處理最大權值節點時,其所有邊的代價已確定為鄰居權值;隨後遞歸處理剩餘子圖。這將問題分解為最優子結構,符合貪心選擇性質。
max(v[u], v[v]),答案同理為 ∑ max(...)。min(節點刪除成本),同樣套用。