首页 > 代码库 > Codevs 2796 最小完全图

Codevs 2796 最小完全图

2796 最小完全图

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

题目描述 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,所有的边权<2^31。

 

/*树就是不存在环的图,而完全图就要求我们把树上的点间关系全部变成环 首先把各边从小到大排序,以保证从小的开始,结果更优 以树上的每条边为基底,进行合并比如用到边i,其端点为a,b将b所在的树合并到a所在的树上,也就是要求两棵小树中所有的点构成一个小的完全图 那么从b树上所有点都向a图上所有点连一条长为v[i]+1的线即可,这样的线一共有siz[a]*siz[b]-1条 上式中"-1"代表的那条边就是边i,其边权为v[i] 就这样跑完最小生成树的所有边,同时将边权累加即可 最后提醒 所有的边权<2^31,别忘了用long long */#include<iostream>#include<cstdio>#include<algorithm>using namespace std;long long siz[20010],n,ans,father[20010];struct node{    long long from,to,v;}e[20010];long long find(long long a){    if(father[a]==a)return father[a];    else return father[a]=find(father[a]);}long long cmp(node a,node b){    return a.v<b.v;}int main(){    scanf("%d",&n);    for(long long i=1;i<n;i++)scanf("%d%d%d",&e[i].from,&e[i].to,&e[i].v);    for(long long i=1;i<=n;i++)father[i]=i,siz[i]=1;    sort(e+1,e+n,cmp);    for(long long i=1;i<n;i++){        long long a=e[i].from,b=e[i].to;        long long f1=find(a),f2=find(b);        father[f2]=f1;        ans+=e[i].v;        long long value=http://www.mamicode.com/siz[f1]*siz[f2]-1;        ans+=value*(e[i].v+1);        siz[f1]+=siz[f2];//与19行对应,注意是谁变成了谁的子树     }    cout<<ans;}

 

Codevs 2796 最小完全图