zoukankan      html  css  js  c++  java
  • 牛客-Highway

    题目传送门

    sol:看了题意显然是最大生成树,但是任意两个点之间都有边,大概有n*n条边。用朴素的最小生成树算法显然不行。联想了一下树的直径还是不会。看了大佬的题解,懂了。。。

    所以还是直接贴大佬博客链接好了:https://blog.csdn.net/yasola/article/details/72229734

    • 树的直径
      #include "bits/stdc++.h"
      using namespace std;
      typedef long long LL;
      typedef pair<int, int> PII;
      typedef pair<int, LL> PIL;
      const int MAXN = 1e5 + 10;
      vector<PII> edge[MAXN];
      LL _max; int nn1, nn2;
      LL dis[MAXN];
      PIL get_diameter(int rt, int fa) {
          LL m1 = 0, m2 = 0;
          int n1 = rt, n2 = rt;
          for (PII i : edge[rt]) {
              if (i.first == fa) continue;
              PIL p = get_diameter(i.first, rt);
              if (p.second + i.second > m1) {
                  m2 = m1, n2 = n1;
                  m1 = p.second + i.second;
                  n1 = p.first;
              } else if (p.second + i.second > m2) {
                  m2 = p.second + i.second;
                  n2 = p.first;
              }
          }
          if (m1 + m2 > _max) {
              nn1 = n1, nn2 = n2;
              _max = m1 + m2;
          }
          return {n1, m1};
      }
      void dfs(int rt, int fa, LL mm) {
          dis[rt] = max(dis[rt], mm);
          for (PII i : edge[rt]) {
              if (i.first == fa) continue;
              dfs(i.first, rt, mm + i.second);
          }
      }
      int main() {
          int n;
          while (~scanf("%d", &n)) {
              memset(dis, -1, sizeof(dis));
              for (int i = 1; i <= n; i++) edge[i].clear();
              for (int i = 1; i < n; i++) {
                  int u, v, w;
                  scanf("%d%d%d", &u, &v, &w);
                  edge[u].push_back({v, w});
                  edge[v].push_back({u, w});
              }
              _max = -1;
              get_diameter(1, -1);    // 求出树的直径,以及两个端点; 
              dfs(nn1, -1, 0), dfs(nn2, -1, 0);
              LL sum = 0;
              for (int i = 1; i <= n; i++) sum += dis[i];
              printf("%lld
      ", sum - _max);    // 将两个端点加入集合只用算一次直径,而上面的循环算了两次,所以减掉一个直径; 
          }
          return 0;
      }
  • 相关阅读:
    「2013-8-5」企业基因
    HashMap和ConcurrentHashMap详解
    JVM 详解
    Dubbo 项目学习(四) 接口抽取以及依赖版本统一
    Dubbo 项目学习(三) 消费Dubbo服务
    Dubbo 项目学习(二) 发布Dubbo服务
    Spring Boot 日志问题记录
    Dubbo 项目学习(一) Admin 管理控制台
    Idea 搭建 SSM 项目框架
    Idea 搭建 SSH 项目框架
  • 原文地址:https://www.cnblogs.com/Angel-Demon/p/11623453.html
Copyright © 2011-2022 走看看