zoukankan      html  css  js  c++  java
  • 严格次小生成树

    时间复杂度: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 }
  • 相关阅读:
    MFC STATIC,Picture控件使用及无法添加变量的问题
    MFC listctrl NMCLICK消息 错误 无法从"NMHDR*"转换为"NMITEMACTIVATE"
    vs2008中将开始执行按钮(不调试按钮)添加至标准工具栏方法
    MFC 删除工具栏 默认对话框全屏 修改MFC标题栏的文字 删除菜单栏
    Visual Assist X设置
    MFC禁止窗口最大化按钮和禁止改变窗口大小
    MFC从头开始如何利用MFC分割窗口
    MFC CSplitterWnd窗口分割
    关于VS2008下提示microsoft incremental linker已停止工作的问题
    windows 下codeblocks查看容器值
  • 原文地址:https://www.cnblogs.com/HNFOX/p/11282516.html
Copyright © 2011-2022 走看看