增加了代码可读性, 方便进行复习----
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
typedef long long LL;
const int NUMBER = 1e5 + 10, EDGE_NUMBER = 6e5 + 10;
const int CNT = 17, INF = 0x3f3f3f3f;
const LL LONG_INF = 1e18;
int number, edge_number;
int head[NUMBER], edge_end[EDGE_NUMBER], next_edge[EDGE_NUMBER], weights[EDGE_NUMBER], edge_index;
int arr[NUMBER];
int fa[NUMBER][CNT], dist1[NUMBER][CNT], dist2[NUMBER][CNT], depth[NUMBER];
struct Edge {
int ver1, ver2, val;
bool in_tree;
} edges[EDGE_NUMBER];
bool cmp(const Edge e1, const Edge e2) {
return e1.val < e2.val;
}
int find(int val) {
if (arr[val] != val) arr[val] = find(arr[val]);
return arr[val];
}
void add_edge(int start, int end, int val) {
edge_end[edge_index] = end, next_edge[edge_index] = head[start], weights[edge_index] = val, head[start] = edge_index++;
}
LL kruskal() {
for (int i = 1; i <= number; ++i) arr[i] = i;
LL res = 0;
sort(edges, edges + edge_number, cmp);
for (int i = 0; i < edge_number; ++i) {
Edge curr = edges[i];
int ver1 = curr.ver1, ver2 = curr.ver2, val = curr.val;
int fa1 = find(ver1), fa2 = find(ver2);
if (fa1 == fa2) continue;
res += val;
arr[fa2] = fa1;
edges[i].in_tree = true;
add_edge(ver1, ver2, val);
add_edge(ver2, ver1, val);
}
return res;
}
void bfs() {
int queue[NUMBER];
int head_ptr = 0, tail = -1;
memset(depth, 0x3f, sizeof depth);
depth[0] = 0, depth[1] = 1;
queue[++tail] = 1;
while (head_ptr <= tail) {
int _node = queue[head_ptr++];
for (int i = head[_node]; ~i; i = next_edge[i]) {
int ver = edge_end[i];
if (depth[_node] + 1 < depth[ver]) {
depth[ver] = depth[_node] + 1;
queue[++tail] = ver;
fa[ver][0] = _node;
dist1[ver][0] = weights[i], dist2[ver][0] = -INF;
for (int k = 1; k <= 16; ++k) {
int mid = fa[ver][k - 1];
fa[ver][k] = fa[mid][k - 1];
int val1 = -INF, val2 = -INF;
int dist[4] = {
dist1[ver][k - 1],
dist2[ver][k - 1],
dist1[mid][k - 1],
dist2[mid][k - 1]
};
for (int l = 0; l < 4; ++l) {
int temp = dist[l];
if (temp > val1) {
val2 = val1;
val1 = temp;
}
else if (temp < val1 && temp > val2) val2 = temp;
}
dist1[ver][k] = val1;
dist2[ver][k] = val2;
}
}
}
}
}
int lca(int ver1, int ver2, int val) {
if (depth[ver1] < depth[ver2]) swap(ver1, ver2);
int _arr[EDGE_NUMBER], cnt = 0;
int val1 = -INF, val2 = -INF;
for (int i = 16; i >= 0; --i) {
if (depth[fa[ver1][i]] >= depth[ver2]) {
_arr[cnt++] = dist1[ver1][i];
_arr[cnt++] = dist2[ver1][i];
ver1 = fa[ver1][i];
}
}
if (ver1 != ver2) {
for (int i = 16; i >= 0; --i) {
if (fa[ver1][i] != fa[ver2][i]) {
_arr[cnt++] = dist1[ver1][i];
_arr[cnt++] = dist2[ver1][i];
_arr[cnt++] = dist1[ver2][i];
_arr[cnt++] = dist2[ver2][i];
ver1 = fa[ver1][i];
ver2 = fa[ver2][i];
}
}
_arr[cnt++] = dist1[ver1][0];
_arr[cnt++] = dist2[ver1][0];
_arr[cnt++] = dist1[ver2][0];
_arr[cnt++] = dist2[ver2][0];
}
for (int i = 0; i < cnt; ++i) {
int temp = _arr[i];
if (temp > val1) {
val2 = val1;
val1 = temp;
}
else if (temp < val1 && temp > val2) val2 = temp;
}
if (val1 < val) return val1;
if (val1 == val) return val2;
return -INF;
}
int main() {
memset(head, -1, sizeof head);
scanf("%d%d", &number, &edge_number);
for (int i = 0; i < edge_number; ++i) {
int ver1, ver2, val;
scanf("%d%d%d", &ver1, &ver2, &val);
edges[i] = {ver1, ver2, val};
}
LL min_sum = kruskal();
bfs();
LL res = LONG_INF;
for (int i = 0; i < edge_number; ++i) {
if (edges[i].in_tree) continue;
int ver1 = edges[i].ver1;
int ver2 = edges[i].ver2;
LL val = min_sum + edges[i].val - lca(ver1, ver2, edges[i].val);
res = min(res, val);
}
printf("%lld\n", res);
return 0;
}