首页 > 代码库 > 最小完全图
最小完全图
时间限制: 1 s空间限制: 128000 KB题目等级 : 钻石 Diamond
题目描述 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)相连;
代码实现
1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 using namespace std; 5 const int maxn=2e4+10; 6 const int maxm=4e4+10; 7 long long ans; 8 int n; 9 int a,b,c;10 int h[maxn],hs;11 struct edge{int s,t,w;}e[maxm];12 int f[maxn],sz[maxn];13 int find_f(int k){return f[k]==k?k:f[k]=find_f(f[k]);}14 bool comp(const edge &x,const edge &y){return x.w<y.w;}15 int main(){16 scanf("%d",&n);17 for(int i=1;i<n;i++){18 scanf("%d%d%d",&a,&b,&c);19 e[++hs]=(edge){a,b,c};20 ans+=c;21 }22 sort(e+1,e+hs+1,comp);23 for(int i=1;i<=n;i++) f[i]=i,sz[i]=1;24 for(int i=1;i<=hs;i++){25 a=find_f(e[i].s),b=find_f(e[i].t);26 f[b]=a;27 ans+=1ll*(1ll*sz[a]*sz[b]-1)*(e[i].w+1);28 sz[a]+=sz[b];29 }30 cout<<ans<<endl;31 return 0;32 }
最小完全图
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。