码迷,mamicode.com
首页 > 其他好文 > 详细

构造完全图

时间:2019-11-04 21:32:36      阅读:65      评论:0      收藏:0      [点我收藏+]

标签:math   题目   kruskal   答案   tps   ++   最小生成树   完全   uri   

https://loj.ac/problem/10067

题目描述

??给出一棵最小生成树,求有且仅有这一棵最小生成树的总边权最小的完全图。

思路

??我们考虑对于最小生成树中的一条边,它一定连接着两个连通支\(T1,T2\),并且是连通\(T1、T2\)的边中边权最小的,而我们构造完全图时,一定要将\(T1、T2\)中的节点两两连边,而显然除了最小生成树中的边(设其边权为\(v\))其余边权均为\(v+1\)时边权最小。所以我们可以记录每个连通支中的节点数,进行一次\(Kruskal\),在合并两个连通支时统计答案即可。

代码

#include <bits/stdc++.h>
using namespace std;
const int MAXN=1e5+10;
struct Edge
{
    int x,y,d;
}e[MAXN];
int fa[MAXN],siz[MAXN];
int find(int x)
{
    return fa[x]==x?x:fa[x]=find(fa[x]);
}
bool cmp(Edge x,Edge y)
{
    return x.d<y.d;
}
int main() 
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<n;i++)
        scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].d);
    for(int i=1;i<=n;i++)
        fa[i]=i,siz[i]=1;
    sort(e+1,e+n,cmp);
    long long sum=0;
    int cnt=0;
    for(int i=1;i<n;i++)
    {
        int fx=find(e[i].x),fy=find(e[i].y);
        if(fx!=fy)
        {
            fa[fx]=fy;
            sum+=(long long)(siz[fx]*siz[fy]-1)*(e[i].d+1);
            sum+=e[i].d;
            siz[fy]+=siz[fx];
            cnt++;
            if(cnt==n-1)break ;
        }
    }
    printf("%lld",sum);
    return 0;
}

构造完全图

标签:math   题目   kruskal   答案   tps   ++   最小生成树   完全   uri   

原文地址:https://www.cnblogs.com/fangbozhen/p/11794812.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!