https://codeforces.com/contest/1213/problem/G(图论)
思路:保证每次加入的边一定不会小于现存的图中的边,因为题目保证了一定为一棵树,所以每次加入的边必定属于不同的集合,计算下每个集合的个数,新加入的边一定会增加 sum[u] * sum[v] 所属不同集合的节点个数
]#include<bits/stdc++.h> #define inf (0x3f3f3f3f) using namespace std; typedef long long i64; const int maxn = 2e5 + 32; struct Edge{ int from,to,w; bool operator<(const struct Edge& e) { return w < e.w; } }edge[maxn]; int q[maxn],sum[maxn],p[maxn]; i64 cnt[maxn]; int find(int cur) { if(p[cur] != cur) p[cur] = find(p[cur]); return p[cur]; } int main() { ios::sync_with_stdio(false); cin.tie(0),cout.tie(0); int n,m; cin>>n>>m; for(int i=1;i<=n;++i) p[i] = i,sum[i] = 1; for(int i=1;i<=n-1;++i) cin>>edge[i].from>>edge[i].to>>edge[i].w; sort(edge+1,edge+n); int maxquery = 0; for(int i=1;i<=m;++i) { cin>>q[i]; maxquery = max(maxquery,q[i]); } for(int i=1;i<=n-1;++i) { int p1 = find(edge[i].from); int p2 = find(edge[i].to); cnt[edge[i].w] += (i64)sum[p1] * sum[p2]; p[p1] = p2; sum[p2] += sum[p1]; sum[p1] = 0; } for(int i=1;i<=maxquery;++i) cnt[i] += cnt[i-1]; for(int i=1;i<=m;++i) cout<<cnt[q[i]]<<' '; }