NOIP 2012 中山纪念中学Fortuna 系列模拟赛 Input Solution
题意
给你一棵带边权的树,然后这棵树是某个完全图唯一的最小生成树。问原来的完全图中所有边可能的最小边权和是多少。完全图是任意两个点之间都有边相连的图。
Solution
O(n^3)算法:kruskal 逆推枚举+并查集
O(n):带权并查集+sort
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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\n",ans); 53 } 54 }