[暑假集训Day2T2]走廊泼水节

给定一棵n个点的图上的最小生成树,让你把它补成完全图,使得新图的MST还是给定的MST且边权和最小,输出需要增加的边权和。

设size[i]表示以i号为祖先的并查集的大小。

首先按边权排序,之后在做MST的过程中,答案cnt+=(size[v]*size[u]-1)*(w+1),来解释一下这个式子,从v号集合到u号集合每两个点之间连一条边(除了MST上的这条边),因为MST必须还是原来的MST,所以边权要加1,之后将集合合并直到求出MST为止即可。

下面给出参考代码:

 

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstring>
 4 #define N 6005
 5 using namespace std;
 6 int read()
 7 {
 8     int x=0,f=1;char ch=getchar();
 9     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
10     while(ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();}
11     return x*f;
12 }
13 int t,n,m,x,y,z,cnt,parent[N],size[N];
14 struct node
15 {
16     int u,v,w;
17 }f[N];
18 bool cmp(node a,node b)
19 {
20     return a.w<b.w;
21 }
22 int find(int x)
23 {
24     if(parent[x]==x)return x;
25     return parent[x]=find(parent[x]);
26 }
27 int main()
28 {
29     t=read();
30     while(t--)
31     {
32         cnt=0;
33         n=read();
34         for(int i=1;i<n;i++)
35         {
36             x=read();y=read();z=read();
37             f[i].u=x;f[i].v=y;f[i].w=z;
38         }
39         for(int i=1;i<=n;i++)parent[i]=i,size[i]=1;
40         sort(f+1,f+n,cmp);
41         for(int i=1;i<n;i++)
42         {
43             int u=find(f[i].u),v=find(f[i].v);
44             parent[u]=v;
45             cnt+=(size[u]*size[v]-1)*(f[i].w+1);
46             size[v]+=size[u];
47         }
48         cout<<cnt<<endl;
49     }
50     return 0;
51 }
View Code

 

posted @ 2019-07-11 20:21  shao0320  阅读(134)  评论(0编辑  收藏  举报
****************************************** 页脚Html代码 ******************************************