严格次小生成树

本文深入探讨了次小生成树算法的实现细节,通过枚举不在最小生成树上的边并利用LCA加倍增法求最大值,解决了复杂度较高的问题。文章提供了完整的代码示例,包括LCT和LCA的运用。

时间复杂度: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 }

 

转载于:https://www.cnblogs.com/HNFOX/p/11282516.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值