题目地址:https://ac.nowcoder.com/acm/contest/1056/A
思路:
n个节点的树有n条边,先把边从小到大排序,依次扫描每一条边。
如果是一条边,那么就不需要加边
如果是二条边,需要加一条边,这条边的权值应该是当前边的权值+1,如果加边的权值相同,最小生成树就不唯一
如果是三条边,需要加二条边,二条边权值加起来是(当前权值+1)× 2
......
#include<bits/stdc++.h>
using namespace std;
const int maxn=6000+10;
struct rec
{
int x,y,z;
}edge[maxn*5];
int fa[maxn],s1[maxn],n,m,ans=0,t;//fa为并查集
bool operator <(rec f1,rec f2)
{
return f1.z<f2.z;
}
int get(int x)//搜索所在集合
{
if(x==fa[x])
{
return x;
}
return fa[x]=get(fa[x]);
}
int main()
{
cin>>t;
while(t--)
{
cin>>n;
for(int i=1;i<=n-1;i++)
{
cin>>edge[i].x>>edge[i].y>>edge[i].z;
}
sort(edge+1,edge+n);//按权值从小到大排序
for(int i=1;i<=n;i++)
{
fa[i]=i;
s1[i]=1;
}
ans=0;
for(int i=1;i<=n-1;i++)
{
int x=get(edge[i].x);
int y=get(edge[i].y);
if(x==y)
{
continue;
}
fa[x]=y;//合并集合
ans+=(edge[i].z+1)*(s1[x]*s1[y]-1);
s1[y]+=s1[x];
}
cout<<ans<<endl;
}
return 0;
}

京公网安备 11010502036488号