NOIP 2012 中山纪念中学Fortuna 系列模拟赛 Input Solution

题意

给你一棵带边权的树,然后这棵树是某个完全图唯一的最小生成树。问原来的完全图中所有边可能的最小边权和是多少。完全图是任意两个点之间都有边相连的图。

Solution

O(n^3)算法:kruskal 逆推枚举+并查集

O(n):带权并查集+sort

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <algorithm>
 4 #define ll long long
 5 using namespace std;
 6 inline void read(ll &k)
 7 {
 8     char c=getchar();ll f=1;k=0;
 9     while (c<'0'||c>'9')c=='-'&&(f=-1),c=getchar();
10     while (c>='0'&&c<='9')k=k*10+c-'0',c=getchar();
11     k*=f;
12 }
13 const int maxn=20000+10;
14 struct aa{
15     ll a,b,w;
16 }qaq[maxn];
17 bool cmp(aa i,aa j)
18 {
19     return i.w<j.w;
20 }
21 ll T,n,sum[maxn],fa[maxn],a[maxn],b[maxn],w[maxn],ans;
22 ll gf(ll now)
23 {
24     return fa[now]==now?now:fa[now]=gf(fa[now]);
25 }
26 int main()
27 {
28     freopen("input.in","r",stdin);
29     freopen("input.out","w",stdout);
30     read(T);
31     while (T--)
32     {
33         ans=0;
34         read(n);
35         for (int i=1;i<=n;i++)fa[i]=i;
36         for (int i=1;i<=n;i++)sum[i]=1;
37         for (int i=1;i<n;i++)
38         {
39             read(qaq[i].a);
40             read(qaq[i].b);
41             read(qaq[i].w);
42         }
43         sort(qaq+1,qaq+n,cmp);
44         for (int i=1;i<n;i++)
45         {
46             ll aa=gf(qaq[i].a),bb=gf(qaq[i].b);
47             ans+=qaq[i].w+(qaq[i].w+1)*(sum[aa]*sum[bb]-1);
48             fa[aa]=fa[bb];
49             sum[bb]+=sum[aa];
50         }
51     //    if (!T)cout << sum[1] << " "<<sum[2]<<" "<<sum[3]<<endl;
52         printf("%lld
",ans);
53     }
54 }
View Code
原文地址:https://www.cnblogs.com/mczhuang/p/7496125.html