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