标签:math 题目 kruskal 答案 tps ++ 最小生成树 完全 uri
??给出一棵最小生成树,求有且仅有这一棵最小生成树的总边权最小的完全图。
??我们考虑对于最小生成树中的一条边,它一定连接着两个连通支\(T1,T2\),并且是连通\(T1、T2\)的边中边权最小的,而我们构造完全图时,一定要将\(T1、T2\)中的节点两两连边,而显然除了最小生成树中的边(设其边权为\(v\))其余边权均为\(v+1\)时边权最小。所以我们可以记录每个连通支中的节点数,进行一次\(Kruskal\),在合并两个连通支时统计答案即可。
#include <bits/stdc++.h>
using namespace std;
const int MAXN=1e5+10;
struct Edge
{
int x,y,d;
}e[MAXN];
int fa[MAXN],siz[MAXN];
int find(int x)
{
return fa[x]==x?x:fa[x]=find(fa[x]);
}
bool cmp(Edge x,Edge y)
{
return x.d<y.d;
}
int main()
{
int n;
scanf("%d",&n);
for(int i=1;i<n;i++)
scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].d);
for(int i=1;i<=n;i++)
fa[i]=i,siz[i]=1;
sort(e+1,e+n,cmp);
long long sum=0;
int cnt=0;
for(int i=1;i<n;i++)
{
int fx=find(e[i].x),fy=find(e[i].y);
if(fx!=fy)
{
fa[fx]=fy;
sum+=(long long)(siz[fx]*siz[fy]-1)*(e[i].d+1);
sum+=e[i].d;
siz[fy]+=siz[fx];
cnt++;
if(cnt==n-1)break ;
}
}
printf("%lld",sum);
return 0;
}
标签:math 题目 kruskal 答案 tps ++ 最小生成树 完全 uri
原文地址:https://www.cnblogs.com/fangbozhen/p/11794812.html