6529: 构造完全图 最小生成树
描述
对于完全图G,若有且仅有一棵最小生成树为T,则称完全图G是树T的扩展出的。给你一 棵树T,找出T能扩展出的边权和最小的完全图G。
输入
第一行N表示树T的点数。 接下来N-1行:Si,Ti,Di;描述一条边(Si,Ti)权值为 Di。 保证输入数据构成一棵树。
对于20%的数据,N<=10 对于50%的数据,N<=1000 对于100%的数据,N<=100000,1<=Di<=100000
输出
一个数,表示最小的图G的边权和。
样例输入
4
1 2 1
1 3 1
1 4 2
样例输出
12
这道题解法很巧妙,还是从小到大排序,一条一条往上加。
往上加的同时,记录sum[i]表示以i为根节点的树中含点的个数,很显然,一次操作中所加的边权就是(sum[i]+sum[j]-1)*(v+1)+v其中i表示加入边的起点,j表示终点,v表示边权
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N = 1e5+10,inf = 0x3f3f3f3f; struct node{ int x,y,t; }; node a[N]; int n,f[N],sum[N];//f[i]i的父节点,sum[i]以i为父节点的家族人数 bool cmp(node a,node b) { return a.t<b.t; } int find(int x) { if(f[x]!=x)f[x] = find(f[x]); return f[x]; } int main() { cin >> n; for(int i=1;i<=n-1;i++) { scanf("%d %d %d",&a[i].x,&a[i].y,&a[i].t); } sort(a+1,a+n,cmp); for(int i=1;i<=n;i++) { f[i] = i;sum[i] = 1; } ll ans = 0; for(int i=1;i<=n-1;i++) { int fx = find(a[i].x); int fy = find(a[i].y); if(fx!=fy) { f[fy] = fx; ans += ll((ll)sum[fx]*sum[fy]-1)*(a[i].t+1)+a[i].t; //完全图公式 sum[fx]+=sum[fy]; } } cout << ans; return 0; }