[最小生成树][并查集]JZOJ 2940 生成输入数据
分析
题目和题面无关系列
考场的时候不知道为什么总觉得可以有奇怪的方法,打了一波计算用set维护然后20分WA
事实上只用模仿生成最小生成树的过程即可
我们合并两棵树时,我们可以确定其中必定只有一条边是最小生成树内的,需要添加的边数=两棵树大小的乘积-1,边的权值为最小生成树树边的权值+1
然后再加上原树总值就算出来了
#include <iostream> #include <cstdio> #include <algorithm> using namespace std; const int N=2e4+10; struct Edge { int u,v,w; }g[N]; int f[N],sz[N]; int T,n; int Get_F(int x) {return f[x]==x?x:f[x]=Get_F(f[x]);} bool CMP(Edge a,Edge b) { return a.w<b.w; } int main() { for (scanf("%d",&T);T;T--) { scanf("%d",&n); for (int i=1;i<n;i++) scanf("%d%d%d",&g[i].u,&g[i].v,&g[i].w),sz[i]=1,f[i]=i; f[n]=n;sz[n]=1;long long ans=0; sort(g+1,g+n,CMP); for (int i=1;i<n;i++) { int fu=Get_F(g[i].u),fv=Get_F(g[i].v); if (fu!=fv) { ans+=1ll*(sz[fu]*sz[fv]-1ll)*(g[i].w+1ll); sz[fu]+=sz[fv]; f[fv]=fu; ans+=g[i].w; } } printf("%lld\n",ans); } }
在日渐沉没的世界里,我发现了你。