A - 木の重み付け / Weighting a Tree Editorial by admin
GLM 5.2 (High)概要\(N\) 頂点の木があり、各辺に正の整数の乗数を設定して、任意のパス上での乗数の和がパス長の2乗以下になるようにします。全辺のコスト(重み \(\times\) 乗数)の合計を最小化する問題です。
考察
まず、各辺の乗数 \(r_i\) は \(1\) 以上の整数という制約があります。したがって、各辺のコスト \(w_i \times r_i\) は常に \(w_i\) 以上となります。これを全ての辺について足し合わせると、全辺のコストの合計は \(\sum w_i \times r_i \geq \sum w_i \times 1 = \sum w_i\) となり、\(\sum w_i\) が理論上の下限値であることがわかります。
次に、この下限値を達成できるかを考えます。問題文のヒントにもある通り、すべての辺の乗数を \(r_i = 1\) に設定してみます。 任意の相異なる2頂点間のパス長を \(k\) とすると、パス上の乗数の和は \(r_{e_1} + \cdots + r_{e_k} = 1 + \cdots + 1 = k\) となります。 パス上の2頂点は相異なるため、パス長 \(k\) は \(1\) 以上の整数になります。\(k \geq 1\) のとき、不等式 \(k \leq k^2\) は常に成立します。
したがって、すべての辺の乗数を \(1\) に設定することは条件を満たし、このときの全辺のコストの合計はちょうど下限値である \(\sum w_i\) となります。よって、求める最小値は \(\sum w_i\) となります。
アルゴリズム
木の構造や頂点番号を記録する必要はなく、入力として与えられた \(N-1\) 個の辺の重み \(w_i\) をそのまま足し合わせるだけで答えが求まります。
計算量
- 時間計算量: \(O(N)\)
- 空間計算量: \(O(1)\)
実装のポイント
重み \(w_i\) は最大 \(10^9\)、辺の数は最大 \(2 \times 10^5\) であるため、合計値は最大 \(2 \times 10^{14}\) になります。32ビット整数(
int型など)ではオーバーフローするため、64ビット整数(C++ならlong long型、Pythonなら標準の整数型)を用いて計算する必要があります。ソースコード
#include <iostream>
using namespace std;
int main() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin >> n;
long long sum = 0;
for (int i = 0; i < n - 1; i++) {
int u, v;
long long w;
cin >> u >> v >> w;
sum += w;
}
cout << sum << '\n';
return 0;
}
この解説は or-glm5.2-high によって生成されました。