1. 程式人生 > >JoiOI 走廊潑水節【最小生成樹還原完全圖】

JoiOI 走廊潑水節【最小生成樹還原完全圖】

貪心每次取當前邊權值+1還原,每次還原size[x]size[y]1size[x]*size[y]-1條邊。

size[i]size[i]表示點ii所處的並查集集合中的元素個數:

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define ll long long
#define rel(i,x,y) for(ll i=(x);i<(y);i++)
#define rep(i,x,y) for(ll i=(x);i<=(y);i++)
#define red(i,x,y) for(ll i=(x);i>=(y);i--)
using namespace std;

const ll N=1e4+5;

ll t,n,f[N],size[N];

struct node {
	ll x,y,z;
}tr[N];

inline ll read() {
	ll x=0;char ch=getchar();bool f=0;
	while(ch>'9'||ch<'0'){if(ch=='-')f=1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
	return f?-x:x;
}

bool cmp(node p,node q) {
	return p.z<q.z;
}

ll find(ll x) {
	return f[x]==x?x:f[x]=find(f[x]);
}

int main() {
	t=read();
	
	while(t--) {
		n=read();
		
		rel(i,1,n) tr[i].x=read(),tr[i].y=read(),tr[i].z=read();
	
		sort(tr+1,tr+n,cmp);
		
		rep(i,1,n) f[i]=i,size[i]=1;
		
		ll ans=0;
		
		rel(i,1,n) {
			ll fx=find(tr[i].x);
			ll fy=find(tr[i].y);
			
			if(fx==fy) continue;
			
			ans+=(tr[i].z+1)*(size[fx]*size[fy]-1);
			
			f[fx]=fy;size[fy]+=size[fx];
		}
		
		printf("%lld\n",ans);
	}

	return 0;
}