♻️lzhh_lzhh32 • 3个月前
//kruscal
/*
a,b两点加边,要求满足加边的权值是a到b路径上最大边权值+1
*/
#include<iostream>
#include<algorithm>
using namespace std;
int n;
struct edge{
int a,b;
int len;
bool operator < (edge e2){ //重载运算符
return len<e2.len;
}
}list[20005];
int group[10005];
int gc[10005]; //记录连通分量点数
int find(int x){
if(x!=group[x]){
group[x]=find(group[x]);
}
return group[x];
}
int main(){
scanf("%d",&n); //n点
for(int i=0;i<n-1;i++){
cin>>list[i].a>>list[i].b>>list[i].len;
}
long long ans=0;
//完全图,每个节点度必为n-1,故遍历,找度不是n-1的点
sort(list,list+n-1);
for(int i=0;i<n;i++){
group[i+1]=i+1;
gc[i+1]=1; //初始化为1
}
for(int i=0;i<n-1;i++){ //假装进行kruskal
ans+=(list[i].len+1)*(gc[find(list[i].a)]*gc[find(list[i].b)]-1);
//边点A所在连通分量所有点和边点B所在连通分量所有点两两相连加新边,权值为当前边+1
//因为kruscal算法每次新加边一定是路径上的最长边
gc[find(list[i].b)]+=gc[find(list[i].a)]; //连通分量点数合并
gc[find(list[i].a)]=0; //被合并的连通分量点数清零
group[find(list[i].a)]=group[find(list[i].b)]; //得先合并数量再合并编号
}
cout<<ans<<endl;
return 0;
}
评论:
请先登录,才能进行评论