目录
Description
有一棵树,计算 \(\sum_{i=1}^{n-1}\sum_{j=i+1}^{n}f(i,j)\), 其中 \(f(i,j)\) 代表 \(i,j\) 两个节点之间最短路径上的最大边权
State
\(1<=n<=10^{5}\)
\(1<=u,v<=n\)
\(1<=w<=10^7\)
Input
5
1 2 1
2 3 2
4 2 5
3 5 14
Output
76
Solution
题目属于贡献题,即每条边对答案的贡献是是多少
看一下样例中的 \(2,4\) 这条边,边权 \(x=5\) 对答案的贡献为 \(3x\) ,不难发现,较大的边权会将较小的边权覆盖,所以按照边权顺序来;
一条边左右两个端点各形成两棵树,而且边权一定小,所以这两棵树的大小相乘便是这条边的贡献
Code
const int N = 2e5 + 5;
ll n, m, _;
int i, j, k;
tuple<int, int ,int> a[N];
int fa[N];
int sz[N];
int Find(int x)
{
if(x == fa[x]) return x;
else return fa[x] = Find(fa[x]);
}
void Union(int x, int y)
{
int nx = Find(x), ny = Find(y);
if(nx != ny){
fa[nx] = ny;
sz[ny] += sz[nx];
}
return void();
}
signed main()
{
//IOS;
while(~ sd(n)){
rep(i, 1, n){
fa[i] = i;
sz[i] = 1;
}
rep(i, 1, n - 1){
sddd(get<1>(a[i]), get<2>(a[i]), get<0>(a[i]));
}
sort(a + 1, a + 1 + n);
ll ans = 0;
rep(i, 1, n){
int x = Find(get<1>(a[i])), y = Find(get<2>(a[i]));
ans += (ll)sz[x] * sz[y] * get<0>(a[i]);
Union(x, y);
}
pll(ans);
}
//PAUSE;
return 0;
}