6529: 构造完全图 最小生成树

描述

 

对于完全图G,若有且仅有一棵最小生成树为T,则称完全图G是树T的扩展出的。给你一 棵树T,找出T能扩展出的边权和最小的完全图G。

 

输入

 

第一行N表示树T的点数。 接下来N-1行:Si,Ti,Di;描述一条边(Si,Ti)权值为 Di。 保证输入数据构成一棵树。

对于20%的数据,N<=10 对于50%的数据,N<=1000 对于100%的数据,N<=100000,1<=Di<=100000

 

输出

 

 

一个数,表示最小的图G的边权和。

 

 

样例输入

 

4
1 2 1
1 3 1
1 4 2

样例输出

12

这道题解法很巧妙,还是从小到大排序,一条一条往上加。
往上加的同时,记录sum[i]表示以i为根节点的树中含点的个数,很显然,一次操作中所加的边权就是(sum[i]+sum[j]-1)*(v+1)+v其中i表示加入边的起点,j表示终点,v表示边权

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5+10,inf = 0x3f3f3f3f;
struct node{
    int x,y,t;
};
node a[N];
int n,f[N],sum[N];//f[i]i的父节点,sum[i]以i为父节点的家族人数 
bool cmp(node a,node b)
{
    return a.t<b.t;
}
int find(int x)
{
    if(f[x]!=x)f[x] = find(f[x]);
    return f[x];
}
int main()
{

    cin >> n;
    for(int i=1;i<=n-1;i++)
    {
        scanf("%d %d %d",&a[i].x,&a[i].y,&a[i].t);
    }
    sort(a+1,a+n,cmp);
    for(int i=1;i<=n;i++)
    {
        f[i] = i;sum[i] = 1;
    }
    ll ans = 0;
    for(int i=1;i<=n-1;i++)
    {
        int fx = find(a[i].x);
        int fy = find(a[i].y);
        if(fx!=fy)
        {
            f[fy] = fx;
            ans += ll((ll)sum[fx]*sum[fy]-1)*(a[i].t+1)+a[i].t; //完全图公式 
            sum[fx]+=sum[fy];
        }
    }
    cout << ans;
     return 0;
}

 

posted @ 2023-08-11 19:05  CRt0729  阅读(79)  评论(0编辑  收藏  举报