【NOIP2012模拟8.10】生成输入数据
这题可以很容易就想到,
由于我们要将最小生成树变成原来的完全图,而且要使边权和最小。
那么:如果我们在x和y连一条边,那么这条边的长度变为↙
那个最小生成树中x到y的路径上最大的边权+1。
这样子暴力O(n2),只能拿50分。
我们考虑优化。(用并查集)
模拟一遍最小生成树,每次合并的时候记录一下每块的个数,并添加答案。
上标:
#include<cstdio>
#include<cstring>
#include<algorithm>
#define max(x,y) x>y ? x:y
using namespace std;
struct node{int a,b,w;}a[20010];
int T,n,fa[20010],son[20010];
long long ans=0;
inline int read()
{
int x=0; char c=getchar();
while (c<'0' || c>'9') c=getchar();
while (c>='0' && c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return x;
}
int cmp(node x,node y) {return x.w<y.w;}
int gf(int x)
{
if (!fa[x]) return x;
son[fa[x]]+=son[x],son[x]=0;
return fa[x]=gf(fa[x]);
}
int main()
{
freopen("B.in","r",stdin);
// freopen("B.out","w",stdout);
T=read();
while (T--)
{
n=read();
for (int i=1;i<=n;i++) son[i]=1,fa[i]=0;
for (int i=1;i<n;i++)
a[i].a=read(),a[i].b=read(),a[i].w=read();
sort(a+1,a+n,cmp);ans=0;
for (int i=1,x,y;i<n;i++)
{
x=gf(a[i].a),y=gf(a[i].b);
ans+=((long long)son[x]*son[y])*(a[i].w+1)-1;
fa[x]=y;son[y]+=son[x],son[x]=0;
}
printf("%lld\n",ans);
}
return 0;
}
转载需注明出处。