zoukankan      html  css  js  c++  java
  • 【并查集】tree

    tree

    时间限制:1秒  内存限制: 64 MB

    试题描述

        对于完全图G,若有且仅有一棵最小生成树为T,则称完全图G是树T的扩展出的。给你一棵树T,找出T能扩展出的边权和最小的完全图G。

    输入要求

         第一行N,(2 <= N <= 10^5)表示树T的点数。 接下来N-1行,Si Ti Di 描述一条边(Si,Ti)权值为 Di。 保证输入数据构成一棵树。

    输出要求

         一行一个数,表示最小的图G的边权和。

    输入样例

    4 1 2 1 1 3 1 1 4 2

    输出样例

    12

    知识点及提示

         添加D(2,3)=2,D(3,4)=3,D(1,4)=3即可。

     题目解析 :首先回顾一下Kruskal算法求最小生成树的方法 -- 将所有的边进行排序,由小到大依次尝试添加进最小生成树中。如果满足这条边的2个端点u和v不连通,那么将这条边加入最小生成树中,否则不能加入。

           借鉴这种方法,将所有的边进行排序,由小到大开始添加进最小生成树。对于当前这条边的2个端点u和v,所处的2个连通块U和V之间必然是还未连通的。加入这条边之后2个才能够连通,换言之,使得这2个连通块连通的权值最小的边就是当前的u和v边。因此被排除的边就是Sum(U)*Sum(V) -1(U中取一个点,V中取一个点,然后排除u,v这条边),而这条边的权值就是w(u,v) + 1。

     

    代码如下 :

     

     1 #include <cstdio>
     2 #include <algorithm>
     3 
     4 #define rep(i, x) for (int i = 1; i <= x; i ++)
     5 
     6 #define WINDOWS
     7 
     8 using namespace std;
     9 
    10 #ifdef WINDOWS
    11 typedef __int64 int64;
    12 #else
    13 typedef long long int64;
    14 #endif
    15 
    16 const int Maxn = 1e5 + 1;
    17 
    18 struct edge
    19 {
    20     int x, y;
    21     int64 c;
    22 }A[Maxn];
    23 
    24 int N, F[Maxn];
    25 int64 Sum[Maxn], Ans;
    26 
    27 void Print()
    28 {
    29     printf("%I64d", Ans);
    30 }
    31 
    32 void Set_Combine(int x, int y)
    33 {
    34     F[x] = y;
    35     Sum[y] += Sum[x];
    36 }
    37 
    38 int Set_Find(int k)
    39 {
    40     return F[k] == k ? k : F[k] = Set_Find(F[k]);
    41 }
    42 
    43 void Set_Init()
    44 {
    45     rep(i, N) { F[i] = i; Sum[i] = 1; }
    46 }
    47 
    48 bool Cmp(edge a, edge b)
    49 {
    50     return a.c < b.c;
    51 }
    52 
    53 void Solve()
    54 {
    55     sort(A + 1, A + N, Cmp);
    56     Set_Init();
    57     rep(i, N - 1)
    58     {
    59         int x = Set_Find(A[i].x), y = Set_Find(A[i].y);
    60         Ans += (Sum[x] * Sum[y] - 1) * (A[i].c + 1);
    61         Set_Combine(x, y);
    62     }
    63 }
    64 
    65 inline void Scan(int &x)
    66 {
    67     char c;
    68     while (c = getchar(), c < '0' || c > '9'); x = c - '0';
    69     while (c = getchar(), c >= '0' && c <= '9') x = x * 10 + c - '0';
    70 }
    71 
    72 inline void Scan(int64 &x)
    73 {
    74     char c;
    75     while (c = getchar(), c < '0' || c > '9'); x = c - '0';
    76     while (c = getchar(), c >= '0' && c <= '9') x = x * 10 + c - '0';
    77 }
    78 
    79 void Init()
    80 {
    81     Scan(N);
    82     rep(i, N - 1)
    83     {
    84         Scan(A[i].x); Scan(A[i].y); Scan(A[i].c);
    85         Ans += A[i].c;
    86     }
    87 }
    88 
    89 int main()
    90 {
    91     Init();
    92     Solve();
    93     Print();
    94     return 0;
    95 }

     

     

  • 相关阅读:
    20162317袁逸灏 第四周实验报告:实验一 线性结构
    仿ArrayList功能的bag类
    算法复杂度课后作业
    20162317 2017-2018-1 《程序设计与数据结构》第3周学习总结
    学号 2017-2018-1 《程序设计与数据结构》第1周学习总结
    Android:有关下拉菜单导航的学习(供自己参考)
    Android:有关菜单的学习(供自己参考)
    Java:类集框架中集合的学习
    20162305李昱兴 2017-2018-1 《程序设计与数据结构》第1周学习总结
    第十六周 数据库课堂实践 20162305 李昱兴
  • 原文地址:https://www.cnblogs.com/GXZC/p/2829044.html
Copyright © 2011-2022 走看看