官方題解:
把1看成整棵樹的根. 問題相當於把2∼n每個點一個[1,k]的標號. 然後根據最小斯坦納樹的定義, (x,fax) 這條邊的貢獻是 x 子樹內不同標號的個數目difi. 那麼顯然有difi≤min(k,szi), szi表示子樹大小. 可以通過構造讓所有difi都取到最大值. 所以答案就是∑x=2nw[x][fax]∗min(szx,k)時間複雜度爲O(n)。代碼如下:
#include <bits/stdc++.h>
using namespace std;
typedef long long int LL;
const int MOD = 1e9 + 7;
const int MAX_N = 1e6 + 5;
const int INF = 0x3f3f3f3f;
int n, k;
struct edge
{
int to;
int cost;
};
vector<edge> G[MAX_N];
int siz[MAX_N];
int pre[MAX_N];
void dfs(int u, int fa)
{
siz[u] = 1;
for (unsigned i = 0; i < G[u].size(); i++)
{
int v = G[u][i].to;
int w = G[u][i].cost;
if (v == fa)
continue;
dfs(v, u);
pre[v] = w;
siz[u] += siz[v];
}
}
int main()
{
//freopen("test.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
cin.sync_with_stdio(false);
while (cin >> n >> k)
{
for (int i = 0; i < MAX_N; i++)
G[i].clear();
for (int i = 1; i < n; i++)
{
int u, v, cost;
cin >> u >> v >> cost;
G[u].push_back({v, cost});
G[v].push_back({u, cost});
}
dfs(1, -1);
LL ans = 0;
for (int i = 2; i <= n; i++)
ans += (LL)pre[i] * min(siz[i], k);
cout << ans << endl;
}
return 0;
}