传送门:https://www.luogu.com.cn/problem/P4180
类似于CF1108F,而由于严格次小,可能出现非树边与生成树上最大边权相同的情况,我们需要预处理树上最大和严格次大边。
#include <bits/stdc++.h>#define int long long
#define inf 0x3f3f3f3f3f3f3f3fusing 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;
}