宿命的PSS
时间限制: 1 Sec 内存限制: 128 MB
提交: 60 解决: 37
题目描述
最小生成树P.S.S在宿命的指引下找到了巫师Kismi。P.S.S希望Kismi能帮自己变成一个完全图。Kismi由于某些不可告人的原因,把这件事交给了你。 PS: 可以保证,这个最小生成树对于最后求出的完全图是唯一的。
输入
输入的第一行是一个整数n,表示生成树的节点数。 接下来有n-1行,每行有三个正整数,依次表示每条边的端点编号和边权。 (顶点的边号在1-n之间,边权< maxint)
输出
一个整数ans,表示以该树为最小生成树的最小完全图的边权之和。
样例输入
3
1 2 4
2 3 7
样例输出
19
提示
n< 20000
样例输入2:
4
1 2 1
1 3 1
样例输出2:
12
题解:可以用并查集祖先来记录该块的个数,然后连接两个块时计算需要加入的边的条数,然后乘以该最小生成树的边权+1这样即可。
1 #include<cstdio>
2 #include<iostream>
3 #include<algorithm>
4 #include<cmath>
5 #include<cstring>
6 #include<string>
7
8 using namespace std;
9 const int MAXN=20007;
10
11 struct fzy
12 {
13 int u,v,zhi;
14 }a[MAXN];
15 struct xx
16 {
17 int anc,num;
18 void cc(int i)
19 {
20 anc=i;
21 num=1;
22 }
23 }f[MAXN];
24
25 long long ans,sum;
26 int n;
27
28 int find(int num)
29 {
30 if (f[num].anc!=num) f[num].anc=find(f[num].anc);
31 return f[num].anc;
32 }
33 bool cmp(fzy a,fzy b)
34 {
35 return a.zhi<b.zhi;
36 }
37 int main()
38 {
39 int x,y,z;
40 ans=0;
41
42 scanf("%d",&n);
43 for (int i=1;i<=n;i++)
44 f[i].cc(i);
45 for (int i=1;i<n;i++)
46 {
47 scanf("%d%d%d",&a[i].u,&a[i].v,&a[i].zhi);
48 sum+=a[i].zhi;
49 }
50
51 sort(a+1,a+n,cmp);
52
53 for (int i=1;i<n;i++)
54 {
55 x=find(a[i].u),y=find(a[i].v);
56 if (f[x].anc!=f[y].anc)
57 {
58 f[y].anc=f[x].anc;
59 ans+=(long long)((long long)f[x].num*f[y].num-1)*(a[i].zhi+1);
60 f[x].num+=f[y].num;
61 }
62 }
63
64 ans+=sum;
65 printf("%lld",ans);
66 }
View Code