LOJ10067

LOJ10067 构造完全图

给你一棵树 T,找出 T 能扩展出的边权和最小的完全图 G。
第一行 N 表示树 T 的点数;
保证输入数据构成一棵树。
输出仅一个数,表示最小的完全图 G 的边权和。
4
1 2 1
1 3 1
1 4 2
 
12
___________________________________________________________________________________
既然要求的是最小完全图,那么也就是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 on 2019-03-07 10:51  gryzy  阅读(110)  评论(0编辑  收藏  举报

导航