题目传送门
题意简化:给你一棵树,要求你加边使它成为完全图(任意两点间均有一边相连) ,满足原来的树是这个图的最小生成树。求加边的价值最小是多少。
考虑Kruskal的过程,我们每次找一条最短的,两边的集合没有并在一起的两条边。
而且有个结论:边权最小的边一定在图的最小生成树中。于是我们加的所有边一定要比原边权恰好多1,这样是最贪心的。
然后每次加边的时候一定加的是$size[x]*size[y]-1$这么多个。
Code
1 #include<cstdio> 2 #include<algorithm> 3 4 using namespace std; 5 typedef long long ll; 6 7 int T,n; 8 int fa[7000],size[7000]; 9 ll ans; 10 struct node{ 11 int f,t,w; 12 }edge[50000]; 13 14 bool cmp(node a,node b) 15 { 16 return a.w<b.w; 17 } 18 19 int getf(int x) 20 { 21 if(x==fa[x]) return x; 22 return fa[x]=getf(fa[x]); 23 } 24 25 int main() 26 { 27 scanf("%d",&T); 28 while(T--) 29 { 30 scanf("%d",&n); 31 for(int i=1;i<n;i++) 32 scanf("%d%d%d",&edge[i].f,&edge[i].t,&edge[i].w); 33 sort(edge+1,edge+1+n-1,cmp); 34 for(int i=1;i<=n;i++) fa[i]=i,size[i]=1; 35 for(int i=1;i<n;i++) 36 { 37 int pp=getf(edge[i].f); 38 int qq=getf(edge[i].t); 39 if(pp==qq) continue; 40 ans+=1ll*(size[pp]*size[qq]-1)*(edge[i].w+1); 41 fa[pp]=qq; 42 size[qq]+=size[pp]; 43 } 44 printf("%lld\n",ans); 45 ans=0; 46 } 47 return 0; 48 }