傳送門:https://www.luogu.com.cn/problem/P4180
類似於CF1108F,而由於嚴格次小,可能出現非樹邊與生成樹上最大邊權相同的情況,我們需要預處理樹上最大和嚴格次大邊。
#include <bits/stdc++.h>
#define int long long
#define inf 0x3f3f3f3f3f3f3f3f
using namespace std;
const int N = 6e5 + 10;
inline int read() {
char c;
bool flag = false;
while ((c = getchar()) < '0' || c > '9') if (c == '-') flag = true;
int res = c - '0';
while ((c = getchar()) >= '0' && c <= '9') res = (res << 3) + (res << 1) + c - '0';
return flag ? -res : res;
}
struct E {
int u, v, w, used;
bool operator<(const E &other) const { return w < other.w; }
} e[N];
int pa[N], head[N], cnt, dep[N], fa[N][26], Max[N][26][2];
int get(int u) { return pa[u] == u ? u : pa[u] = get(pa[u]); }
struct Edge {
int to, next, w;
} edge[N];
void add_edge(int u, int v, int w) {
edge[cnt].w = w;
edge[cnt].to = v;
edge[cnt].next = head[u];
head[u] = cnt++;
}
void dfs(int x, int f) {
dep[x] = dep[f] + 1;
fa[x][0] = f;
Max[x][0][1] = -inf;
for (int i = 1; i <= 25; ++i) {
fa[x][i] = fa[fa[x][i - 1]][i - 1];
int temp[4] = {Max[x][i - 1][0], Max[fa[x][i - 1]][i - 1][0], Max[x][i - 1][1], Max[fa[x][i - 1]][i - 1][1]};
sort(temp, temp + 4);
Max[x][i][0] = temp[3];
Max[x][i][1] = temp[2] == temp[3] ? temp[1] : temp[2];
}
for (int i = head[x]; ~i; i = edge[i].next) {
int y = edge[i].to, w = edge[i].w;
if (y == f) continue;
Max[y][0][0] = w;
Max[y][0][1] = -inf;
dfs(y, x);
}
}
int getAns(int x, int lca, int val) {
int m0 = -inf, m1 = -inf;
for (int i = 25; i >= 0; --i) {
if (dep[fa[x][i]] >= dep[lca]) {
if (Max[x][i][0] > m0) m1 = max(m0, Max[x][i][1]), m0 = Max[x][i][0];
else if (Max[x][i][0] > m1 && Max[x][i][0] != m0) m1 = Max[x][i][0];
else if (Max[x][i][0] > m1 && Max[x][i][0] == m0) m1 = max(Max[x][i][1], m1);
x = fa[x][i];
}
}
//cout << "m0:" << m0 << " m1:" << m1 << " val:" << val << endl;
//if (m1 == m0 && m1 != -inf) cout << "SOS";
return m0 == val ? m1 : m0;
}
int lca(int x, int y) {
if (dep[x] < dep[y]) swap(x, y);
for (int i = 25; i >= 0; --i) {
if (dep[fa[x][i]] >= dep[y]) x = fa[x][i];
}
if (x == y) return x;
for (int i = 25; i >= 0; --i) {
if (fa[x][i] != fa[y][i]) x = fa[x][i], y = fa[y][i];
}
return fa[x][0];
}
signed main() {
memset(head, -1, sizeof head);
int n = read(), m = read();
for (int i = 1; i <= m; ++i) {
e[i].u = read(), e[i].v = read(), e[i].w = read();
pa[i] = i;
}
sort(e + 1, e + m + 1);
int ans = inf, res = 0;
for (int i = 1; i <= m; ++i) {
int u = e[i].u, v = e[i].v;
if (get(u) != get(v)) {
pa[get(u)] = get(v);
add_edge(u, v, e[i].w);
add_edge(v, u, e[i].w);
res += e[i].w;
e[i].used = 1;
}
}
dfs(1, 0);
for (int i = 1; i <= m; ++i) {
if (!e[i].used && e[i].u != e[i].v) {
//cout << e[i].w << endl;
int LCA = lca(e[i].u, e[i].v);
int tmp = max(getAns(e[i].u, LCA, e[i].w), getAns(e[i].v, LCA, e[i].w));
if (tmp <= -inf) continue;
ans = min(ans, res + e[i].w - tmp);
//cout << "tmp:" << tmp << " Res:" << res + e[i].w - tmp << endl;
}
}
printf("%lld\n", ans);
return 0;
}