LOJ10067 构造完全图
题目描述
对于完全图 G,若有且仅有一棵最小生成树为 T,则称完全图 G 是树 T 扩展出的。
给你一棵树 T,找出 T 能扩展出的边权和最小的完全图 G。
输入格式
第一行 N 表示树 T 的点数;
接下来 N-1 行三个整数 Si,Ti,Di;描述一条边(Si,Ti)权值为 Di;
保证输入数据构成一棵树。
输出格式
输出仅一个数,表示最小的完全图 G 的边权和。
样例
样例输入
4
1 2 1
1 3 1
1 4 2
样例输出
12
样例说明
添加 D(2, 3)=2, D(3, 4)=3, D(2, 4)=3 即可。
数据范围与提示
对于 20% 的数据,N≤10;
对于 50% 的数据,N≤1000;
对于 100% 的数据,N≤10^5,1≤Di≤10^5。
___________________________________________________________________________________
既然要求的是最小完全图,那么也就是1、图的最小生成树是给定的树,2、图最小
首先、把树上的边按从小到大排序。
然后、从小到大依次取边,这条边对应的两个联通分量的其他点连接边应该比该边大1,所以大小就是(siz[u]*siz[v]-1)*(e[i].w+1)
最后、上面所有新加边的和,再加上树上边的和,就是结果。
___________________________________________________________________________________
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const ll maxn=1e5+10; 5 ll js,n; 6 struct edge 7 { 8 ll u,v,w; 9 }e[maxn]; 10 long long ans; 11 void addage(ll u,ll v,ll w) 12 { 13 e[js].u=u;e[js].v=v;e[js++].w=w; 14 } 15 bool cmp(edge a,edge b) 16 { 17 return a.w<b.w; 18 } 19 ll fa[maxn],sum[maxn]; 20 ll find(ll x) 21 { 22 return fa[x]==x?x:fa[x]=find(fa[x]); 23 } 24 int main() 25 { 26 scanf("%d",&n); 27 for(ll u,v,w,i=1;i<n;++i) 28 { 29 scanf("%lld%lld%lld",&u,&v,&w); 30 addage(u,v,w); 31 ans+=w; 32 } 33 sort(e,e+js,cmp); 34 for(ll i=1;i<=n;++i)fa[i]=i,sum[i]=1; 35 for(ll i=0;i<n-1;++i) 36 { 37 ll a=find(e[i].u),b=find(e[i].v); 38 ans=ans+(sum[a]*sum[b]-1)*(e[i].w+1); 39 fa[a]=b; 40 sum[b]+=sum[a]; 41 } 42 cout<<ans; 43 return 0; 44 }