• 最小完全图


    时间限制: 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 }
  • 相关阅读:
    Daily Scrum (2015/10/28)
    Dailu Scrum (2015/10/27)
    wenbao与cmd
    wenbao与IIS
    wenbao与模板
    wenbao与git
    wenbao与vscode
    wenbao与矩阵
    wenbao与面试题
    wenbao 与将linux系统(kali)装入U盘
  • 原文地址:https://www.cnblogs.com/J-william/p/6849865.html
Copyright © 2020-2023  润新知