https://ac.nowcoder.com/acm/contest/874/G
题目大意:对于一个连通图,现在定义两个点的贡献为连接两点的路径上最大的权值 求任意两个点贡献的和
这个题看懂花了我很久的时间 真的难受
由于两个点的贡献是由最大的权值决定的,所以如果我们将边按权值由小到大排列,那么遍历的时候 当前的边一定是目前的最大权值 也就是两个点之间贡献
本题还用到了并查集来维护连通图
具体看代码吧
#include<bits/stdc++.h> using namespace std; #define maxn 1000000+1000 #define ull unsigned long long int T,n,p[maxn],sz[maxn]; ull ans; struct edge { int u,v,w; bool operator<(edge x) //运算符的重载 方便排序 { return w<x.w; } }e[max]; int findset(int x) { return (x==p[x]?x:p[x]=findset(p[x])); //并查集 } int main() { cin>>T; while(T--) { cin>>n; for(int i=1;i<n;i++)scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w); sort(e+1,e+n); for(int i=1;i<=n;i++)p[i]=i; //一开始是不连通的 分别标上号 for(int i=1;i<=n;i++)sz[i]=1; //所在连通图的大小 ans=0; for(int i=1;i<n;i++) { int u=findset(e[i].u),v=findset(e[i].v); ans+=(ull)sz[u]*sz[v]*e[i].w; //增加的贡献 sz[u]+=sz[v]; //扩大连通图 p[v]=u; //标记连通图 注意要和上一行呼应 保证整合到同一个图里去 } cout<<ans<<endl; } return 0; }