ABC214 D - Sum of Maximum Weights(並查集+圖論)
阿新 • • 發佈:2021-09-01
目錄
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; }