LOJ10067

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% 的数据,N10;
对于 50% 的数据,N1000;
对于 100% 的数据,N10^5,1Di10^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 }
View Code

 

posted @ 2019-03-07 10:47  weiwei100  阅读(360)  评论(0编辑  收藏  举报