走廊泼水节
题目描述
输入格式
第一行t,表示有t组测试数据
对于每组数据,第一行N,表示水龙头的个数(当然也是OIER的个数);
2到N行,每行三个整数X,Y,Z;表示水龙头X和水龙头Y有一条长度为Z的小道
输出格式
对于每组数据,输出一个整数,表示修建的所有道路总长度的最短值。
样例
样例输入
2
3
1 2 2
1 3 3
4
1 2 3
2 3 4
3 4 5
样例输出
4
17
样例解释
第一组数据,在2和3之间修建一条长度为4的道路,是这棵树变成一个完全图,且原来的树依然是这个图的唯一最小生成树.
数据范围与提示
代码
#include <bits/stdc++.h>
using namespace std;
const int maxn=6000+100;
struct node{
int from,to,next,w;
bool operator < (const node&a)const{return w < a.w;}
}e[maxn<<1];
int head[maxn];int cnt;
void add(int x,int y,int z){e[++cnt]=(node){x,y,head[x],z};head[x]=cnt;}
inline int read(){
int k=0,f=1;char ch=getchar();
for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-1;
for(;isdigit(ch);ch=getchar()) k=k*10+ch-'0';
return k*f;
}
int f[maxn],w[maxn];
int find(int x){return f[x]==x?x:(f[x]=find(f[x]));}
int main(){
int T=read();
while(T--){
int n=read();
for(int i=1;i<=n;i++) f[i]=i,w[i]=1;
cnt=0;
for(int i=1;i<n;i++){int x=read(),y=read(),z=read();add(x,y,z+1);}
sort(e+1,e+n);
int tmp=0;
for(int i=1;i<n;i++){
int u=find(e[i].from),v=find(e[i].to);
tmp+=(w[u]*w[v]-1)*e[i].w;
f[u]=v; w[v]+=w[u];
}
printf("%d\n",tmp);
}
}