• 严格次小生成树


    时间复杂度:O(我不会求,但是能过)

    真的好复杂

    但核心思路在与最小生成树与严格次小生成树相比有且只有一条边不同

    所以可以枚举不在最小生成树上的边

    将其插入最小生成树

    不过这样就产生了一个环

    所以必须要在这个环上删去一条最大,且与加入进来的边权值不等的边

    这个过程可以用LCT或者LCA加倍增法求最大值解决

      1 #include<iostream>
      2 #include<string.h>
      3 #include<algorithm>
      4 #include<vector>
      5 #include<map>
      6 #include<bitset>
      7 #include<set>
      8 #include<string>
      9 #if !defined(_WIN32)
     10 #include<bits/stdc++.h>
     11 #endif // !defined(_WIN32)
     12 #define ll long long
     13 #define dd double
     14 using namespace std;
     15 const ll inf = 2004100120040426;
     16 int n, m;
     17 struct edge
     18 {
     19     int from;
     20     int to;
     21     ll weight;
     22     int next;
     23 }g[700007], t[700007];//跑lca的边,跑kruskal的边
     24 int tot;
     25 ll ans = inf, sum;//sum为最小生成树,ans为次小生成树
     26 int head[100086];
     27 int deep[100086];
     28 int p[100086][25];//祖宗
     29 ll Max[100086][25];
     30 ll Min[100086][25];
     31 int f[100086];
     32 bool vis[700007];
     33 void add(int from, int to, ll weight)
     34 {
     35     tot++;
     36     g[tot].from = from;
     37     g[tot].to = to;
     38     g[tot].weight = weight;
     39     g[tot].next = head[from];
     40     head[from] = tot;
     41     return;
     42 }
     43 int find(int x)
     44 {
     45     if (f[x] == x)
     46         return x;
     47     else
     48         return f[x] = find(f[x]);
     49 }
     50 void merge(int a, int b)
     51 {
     52     int x = find(a);
     53     int y = find(b);
     54     if (f[x] != f[y])
     55         f[y] = x;
     56     return;
     57 }
     58 bool cmp(edge x, edge y)
     59 {
     60     return x.weight < y.weight;
     61 }
     62 void dfs(int x, int f)
     63 {
     64     p[x][0] = f;
     65     deep[x] = deep[f] + 1;
     66     for (int i = head[x]; i; i = g[i].next)
     67     {
     68         int to = g[i].to;
     69         if (to == f)
     70             continue;
     71         Max[to][0] = g[i].weight;
     72         Min[to][0] = -inf;
     73         dfs(to, x);
     74     }
     75 }
     76 int lca(int x, int y)
     77 {
     78     if (deep[x] < deep[y])
     79         swap(x, y);
     80     while (deep[x] > deep[y])
     81         x = p[x][(int)log2(deep[x] - deep[y])];
     82     if (x == y)
     83         return y;
     84     for (int k = (int)log2(deep[x]); k >= 0; k--)
     85         if (p[x][k] != p[y][k])
     86         {
     87             x = p[x][k];
     88             y = p[y][k];
     89         }
     90     return p[x][0];
     91 }
     92 ll qmax(int from, int to, int MAX)
     93 {
     94     ll ANS = -inf;
     95     for (int i = 20; i >= 0; i--)
     96     {
     97         if (deep[p[from][i]] >= deep[to])
     98         {
     99             if (MAX != Max[from][i])
    100                 ANS = max(ANS, Max[from][i]);
    101             else
    102                 ANS = max(ANS, Min[from][i]);
    103             to = p[to][i];
    104         }
    105     }
    106     return ANS;
    107 }
    108 void cul()
    109 {
    110     for (int i = 1; i <= 18; i++)
    111     {
    112         for (int j = 1; j <= n; j++)
    113         {
    114             p[j][i] = p[p[j][i - 1]][i - 1];
    115             Max[j][i] = max(Max[j][i - 1], Max[p[j][i - 1]][i - 1]);
    116             Min[j][i] = max(Min[j][i - 1], Min[p[j][i - 1]][i - 1]);
    117             if (Max[j][i - 1] > Max[p[j][i - 1]][i - 1])
    118                 Min[j][i] = max(Min[j][i], Max[p[j][i - 1]][i - 1]);
    119             else if (Max[j][i - 1] < Max[p[j][i - 1]][i - 1])
    120                 Min[j][i] = max(Min[j][i], Max[j][i - 1]);
    121         }
    122     }
    123 }
    124 int main()
    125 {
    126     cin >> n >> m;
    127     for (int i = 1; i <= n; i++)
    128         f[i] = i;
    129     for (int i = 1; i <= m; i++)
    130         cin >> t[i].from >> t[i].to >> t[i].weight;
    131     sort(t + 1, t + 1 + m, cmp);
    132     for (int i = 1; i <= m; i++)
    133     {
    134         int x = t[i].from;
    135         int y = t[i].to;
    136         if (find(x) == find(y))
    137             continue;
    138         sum += t[i].weight;
    139         merge(x, y);
    140         add(x, y, t[i].weight);
    141         add(y, x, t[i].weight);
    142         vis[i] = 1;
    143     }
    144     Min[1][0] = -inf;
    145     deep[1] = 1;
    146     dfs(1, 0);
    147     cul();
    148     for (int i = 1; i <= m; i++)
    149     {
    150         if (!vis[i])
    151         {
    152             int u = t[i].from;
    153             int v = t[i].to;
    154             ll w = t[i].weight;
    155             int LCA = lca(u, v);
    156             ll MAX1 = qmax(u, LCA, w);
    157             ll MAX2 = qmax(v, LCA, w);
    158             ans = min(ans, sum - max(MAX1, MAX2) + w);
    159         }
    160     }
    161     cout << ans << endl;
    162     return 0;
    163 }
  • 相关阅读:
    使用SecureCRT连接虚拟机中Linux系统的详细方法以及虚拟网络配置方法
    虚拟机快照克隆多台的方法
    Linux虚拟机网络设置
    Hadoop学习笔记之一:Hadoop IPC
    webpack超详细配置, 使用教程(图文)
    webstrom提示不见了
    vuejs实现本地数据的筛选分页
    关于手机端audio无法自动播放问题解决方法
    计算机实现加法的学习心得
    计算机编码随记
  • 原文地址:https://www.cnblogs.com/HNFOX/p/11282516.html
Copyright © 2020-2023  润新知