官方题解:
把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;
}