先求一遍最小生成树。然后枚举加入哪条边,然后找这两个端点的LCA,记录路径上的最大值和严格次大值(我用了一种偷懒的方法,不过能过)。为什么记录严格次大值?因为我们需要注意最大值等于你加入的边的情况。
/*
Name: P4180
Copyright: NO
Author: Gensokyo_Alice
Date: 25/9/20 17:46
Description:
*/
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <queue>
#include <stack>
#include <cmath>
#include <set>
#include <map>
using namespace std;
typedef long long ll;
const ll MAXN = 1e6+10;
const ll INF = 0x3f3f3f3f3f3f3f3f;
struct edge {
ll nt, to, v;
} E[MAXN];
struct edg {
ll x, y, v;
friend bool operator < (edg a, edg b) {
return a.v < b.v;
}
} e[MAXN];
struct zt {
ll m1, m2, n;
};
ll q[4], tq, N, M, vis[MAXN], fa[MAXN], W, head[MAXN], cnt = -1, siz[MAXN], dep[MAXN], f[MAXN][22], dis[MAXN][2][22];
zt lca(ll, ll);
void add(ll, ll, ll);
void dfs(ll, ll);
ll find_(ll);
void krus();
void onion(ll, ll);
int main() {
memset(head, -1, sizeof(head));
ios::sync_with_stdio(false);
#ifdef ZZCAKIOI
#endif
cin >> N >> M;
for (ll i = 1; i <= M; i++) cin >> e[i].x >> e[i].y >> e[i].v;
for (ll i = 1; i <= N; i++) fa[i] = i, siz[i] = 1;
krus();
dfs(1, 0);
ll ans = INF;
for (ll i = 1; i <= M; i++) {
if (vis[i]) continue;
zt now = lca(e[i].x, e[i].y);
if (e[i].v == now.m1) ans = min(W - now.m2 + e[i].v, ans);
else ans = min(W - now.m1 + e[i].v, ans);
}
cout << ans << '\n';
return 0;
}
zt lca(ll x, ll y) {
zt ret = {0, 0, 0};
if (dep[x] < dep[y]) swap(x, y);
ll di = dep[x] - dep[y];
for (ll i = 20; ~i; i--) {
if ((di >> i) & 1) {
q[0] = dis[x][0][i], q[1] = dis[x][1][i];
q[2] = ret.m1, q[3] = ret.m2;
sort(q, q+4);
tq = unique(q, q+4) - q;
ret.m1 = q[tq-1], ret.m2 = q[tq-2];
x = f[x][i];
}
}
if (x == y) return ret;
for (ll i = 20; ~i; i--) {
if (f[x][i] != f[y][i]){
q[0] = dis[x][0][i], q[1] = dis[x][1][i];
q[2] = ret.m1, q[3] = ret.m2;
sort(q, q+4);
tq = unique(q, q+4) - q;
ret.m1 = q[tq-1], ret.m2 = q[tq-2];
q[0] = ret.m1, q[1] = ret.m2;
q[2] = dis[y][0][i], q[3] = dis[y][1][i];
sort(q, q+4);
tq = unique(q, q+4) - q;
ret.m1 = q[tq-1], ret.m2 = q[tq-2];
x = f[x][i], y = f[y][i];
}
}
q[0] = dis[x][0][0], q[1] = dis[x][1][0];
q[2] = ret.m1, q[3] = ret.m2;
sort(q, q+4);
tq = unique(q, q+4) - q;
ret.m1 = q[tq-1], ret.m2 = q[tq-2];
q[2] = dis[y][0][0], q[3] = dis[y][1][0];
q[1] = ret.m1, q[0] = ret.m2;
sort(q, q+4);
tq = unique(q, q+4) - q;
ret.m1 = q[tq-1], ret.m2 = q[tq-2];
return ret;
}
void dfs(ll n, ll ff) {
dep[n] = dep[ff] + 1;
f[n][0] = ff;
for (ll i = 1; i <= 20; i++) {
f[n][i] = f[f[n][i-1]][i-1];
q[0] = dis[n][0][i-1], q[1] = dis[n][1][i-1];
q[2] = dis[f[n][i-1]][0][i-1], q[3] = dis[f[n][i-1]][1][i-1];
sort(q, q+4);
tq = unique(q, q+4) - q;
dis[n][0][i] = q[tq-1], dis[n][1][i] = q[tq-2];
}
for (ll i = head[n]; ~i; i = E[i].nt) {
ll v = E[i].to;
if (v == ff) continue;
else {
dis[v][0][0] = E[i].v;
dfs(v, n);
}
}
}
void krus() {
sort(e+1, e+M+1);
for (ll i = 1, ct = 0; i <= M && ct < N-1; i++) {
ll fx = find_(e[i].x), fy = find_(e[i].y);
if (fx != fy) {
onion(fx, fy), ct++, W += e[i].v;
add(e[i].x, e[i].y, e[i].v);
add(e[i].y, e[i].x, e[i].v);
vis[i] = 1;
}
}
}
void onion(ll x, ll y) {
ll fx = find_(x), fy = find_(y);
if (siz[fx] < siz[fy]) fa[fx] = fy, siz[fx] += siz[fy];
else fa[fy] = fx, siz[fy] += siz[fx];
}
void add(ll x, ll y, ll v) {E[++cnt] = {head[x], y, v}, head[x] = cnt;}
ll find_(ll x) {return fa[x] == x ? x : fa[x] = find_(fa[x]);}