记录编号 581272 评测结果 AAAAAAAAAA
题目名称 [TYVJ 1399]走廊泼水节 最终得分 100
用户昵称 Gravatar┭┮﹏┭┮ 是否通过 通过
代码语言 C++ 运行时间 0.046 s
提交时间 2023-07-31 21:44:17 内存使用 2.37 MiB
显示代码纯文本
#include <bits/stdc++.h>
using namespace std;
const int N = 10010;
int t,n;
struct made{
	int x,y,z;
}d[N];
int fa[N],s[N],ans;
int find(int x){
	if(x == fa[x])return x;
	return fa[x] = find(fa[x]);
}
bool cmp(made x,made y){
	return x.z < y.z;
}
int main(){
	freopen("corridor.in","r",stdin);
	freopen("corridor.out","w",stdout);
    scanf("%d",&t);
    while(t--){
    	ans = 0;
    	memset(d,0,sizeof(d));
    	memset(fa,0,sizeof(fa));
    	memset(s,0,sizeof(s));
    	scanf("%d",&n);
    	for(int i = 1;i < n;i++)
    		scanf("%d%d%d",&d[i].x,&d[i].y,&d[i].z);
		for(int i = 1;i <= n;i++)fa[i] = i,s[i] = 1;
		//s[x]表示以x为根的并查集有多少个节点 
		/*当边(x,y,z)中,x属于并查集Sx,y属于并查集Sy
		肯定要在Sx与Sy两集合中连除这条边的所有边
		又要保证边(x,y,z)为最小生成树的一边
		所以把其他边的权值定位z+1
		去掉这条边,两集合共需要添加|Sx|*|Sy|-1条边,然后和并查集 
		*/ 
		sort(d+1,d+n,cmp);//从小往大找 
		for(int i = 1;i < n;i++){
			int x = find(d[i].x),y = find(d[i].y);
			if(x == y)continue;
			fa[x] = y;
			ans += (d[i].z + 1) * (s[x] * s[y] - 1);
			s[y] += s[x];//并查集合并 
		}
		printf("%d\n",ans);
	}
	
	return 0;
	
}