tyvj 1391 走廊泼水节【最小生成树】By cellur925

题目传送门

题意简化:给你一棵树,要求你加边使它成为完全图(任意两点间均有一边相连) ,满足原来的树是这个图的最小生成树。求加边的价值最小是多少。


考虑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 }
View Code

猜你喜欢

转载自www.cnblogs.com/nopartyfoucaodong/p/9785055.html
今日推荐