1. 程式人生 > 實用技巧 >走廊潑水節

走廊潑水節

題目描述

話說,中中帶領的 OIER 們打算舉行一次冬季潑水節,當然這是要祕密進行的,絕對不可以讓中中知道。不過中中可是老江湖了,當然很快就發現了我們的小陰謀,於是他準備好水槍迫不及待的想要加入我們了。

我們一共有 N OIER 打算參加這個潑水節,同時很湊巧的是正好有 N 個水龍頭(至於為什麼,我不解釋)。 N 個水龍頭之間正好有 N-1 條小道,並且每個水龍頭都可以經過小道到達其他水龍頭(這是一棵樹,你應該懂的..)。但是 OIER

門為了迎接中中的挑戰,決定修建一些個道路(至於怎麼修,祕密~),使得每個水龍頭到每個水龍頭之間都有一條直接的道路連線(也就是構成一個完全圖唄~)。但是OIER門很懶得,並且記性也不好,他們只會去走那 N-1 條小道,並且希望所有水龍頭之間修建的道路,都要大於兩個水龍頭之前連線的所有小道(小道當然要是最短的了)。所以神 COW 們,幫那些 OIER 們計算一下吧,修建的那些道路總長度最短是多少,畢竟修建道路是要破費的~~

輸入格式

第一行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的道路,是這棵樹變成一個完全圖,且原來的樹依然是這個圖的唯一最小生成樹.

資料範圍與提示

每個測試點最多 10 組測試資料

50\% n<=1500 ;

100\% n<=6000

100\% 1<=z<=100

程式碼

#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);
	}
}