codevs 2796 最小完全图

2796 最小完全图

 http://codevs.cn/problem/2796/

 时间限制: 1 s
 空间限制: 128000 KB
 
 
题目描述 Description

若一个图的每一对不同顶点都恰有一条边相连,则称为完全图。

最小生成树MST在Smart的指引下找到了你,希望你能帮它变成一个最小完全图(边权之和最小的完全图)。

注意:必须保证这个最小生成树MST对于最后求出的最小完全图是唯一的。

输入描述 Input Description

第一行一个整数n,表示生成树的节点数。

接下来有n-1行,每行有三个正整数,依次表示每条边的顶点编号和边权。

(顶点的边号在1-n之间,边权<231)

输出描述 Output Description

一个整数ans,表示以该树为最小生成树的最小完全图的边权之和。

样例输入 Sample Input

4

1 2 1

1 3 1

1 4 2

样例输出 Sample Output

12

数据范围及提示 Data Size & Hint

30%的数据:n<1000;

100%的数据:n≤20000,所有的边权<231。

 

因为题目输入时是一棵树,所以每一条边一定连接两个之前互不相交的点集

这两个点集 要保证这一条边是两点集间最小的边,且只有这一条,

所以其他的边都要至少比这条边大1

所以,将边从小到大排好序后,并查集

#include<cstdio>
#include<algorithm>
#define N 20001
using namespace std;
int n,siz[N],fa[N];
long long ans,sum;
struct node
{
    int u,v,w;
    bool operator < (node p) const
    {
        return w<p.w; 
    }
}e[N];
int find(int i)
{
    return fa[i]==i ? i:fa[i]=find(fa[i]);
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<n;i++) 
    {
        scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
        sum+=e[i].w;
    }
    sort(e+1,e+n);
    for(int i=1;i<=n;i++) siz[i]=1,fa[i]=i;
    int r1,r2;
    for(int i=1;i<n;i++)
    {
        r1=find(e[i].u);
        r2=find(e[i].v);
        ans+=(1ll*siz[r1]*siz[r2]-1)*(e[i].w+1);
        fa[r1]=r2;
        siz[r2]+=siz[r1]; 
    }
    printf("%lld",ans+sum);
}

 

 

posted @ 2017-05-14 08:55  TRTTG  阅读(303)  评论(0编辑  收藏  举报