MnZn样例没过但A了。。。
建议把样例加入数据
#include<bits/stdc++.h>
#define int long long
#define PP pair <int, int>
using namespace std;
inline int read () {
int s = 0, f = 1;
char ch = getchar ();
while (ch < '0' || ch > '9') {
if (ch == '-') f = -1;
ch = getchar ();
}
while (ch >= '0' && ch <= '9') {
s = (s << 1) + (s << 3) + (ch ^ 48);
ch = getchar ();
}
return s * f;
}
const int N = 3e5 + 10, INF = 4e18;
struct EDGE {
int next, to, z;
} edge[N * 2];
struct fdsa {
int x, y, z;
inline bool operator < (const fdsa& asdf) const {
return z < asdf.z;
}
} e[N];
int head[N], cnt, n, fa[N][30], w[N][30][2], dep[N], m, res, asdfasdfasdf;
int Fa[N];
bool f[N];
map <PP, bool> mm;
int get (int x) {
if (x == Fa[x]) return x;
return Fa[x] = get (Fa[x]);
}
inline void add (int x, int y, int z) {
edge[ ++ cnt].next = head[x];
edge[cnt].to = y;
edge[cnt].z = z;
head[x] = cnt;
}
void dfs (int x, int fffff) {
for (int i = 1; i < 20; i ++ ) {
fa[x][i] = fa[fa[x][i - 1]][i - 1];
w[x][i][0] = max (w[x][i][0], max (w[fa[x][i - 1]][i - 1][0], w[x][i - 1][0]));
if (w[x][i - 1][0] == w[fa[x][i - 1]][i - 1][0]) w[x][i][1] = max (w[x][i][1], max (w[x][i - 1][1], w[fa[x][i - 1]][i - 1][1]));
if (w[x][i - 1][0] > w[fa[x][i - 1]][i - 1][0]) w[x][i][1] = max (w[x][i][1], max (w[x][i - 1][1], w[fa[x][i - 1]][i - 1][0]));
if (w[x][i - 1][0] < w[fa[x][i - 1]][i - 1][0]) w[x][i][1] = max (w[x][i][1], max (w[x][i - 1][0], w[fa[x][i - 1]][i - 1][1]));
}
for (int i = head[x]; i; i = edge[i].next) {
int y = edge[i].to, z = edge[i].z;
if (y == fffff) continue;
fa[y][0] = x;
w[y][0][0] = z;
w[y][0][1] = -INF;
dep[y] = dep[x] + 1;
dfs (y, x);
}
}
inline PP query (int x, int y) {
if (x == y) return {0, 0};
int res1 = -INF, res2 = -INF;
if (dep[x] < dep[y]) swap (x, y);
for (int i = 19; i >= 0; i -- )
if (dep[fa[x][i]] >= dep[y]) {
if (w[x][i][0] > res1) {
res2 = res1;
res1 = w[x][i][0];
}
if (w[x][i][1] > res2) res2 = w[x][i][1];
x = fa[x][i];
}
if (x == y) return {res1, res2};
for (int i = 19; i >= 0; i -- )
if (fa[x][i] != fa[y][i]) {
if (w[x][i][0] > res1) {
res2 = res1;
res1 = w[x][i][0];
}
if (w[x][i][1] > res2) res2 = w[x][i][1];
x = fa[x][i];
if (w[y][i][0] > res1) {
res2 = res1;
res1 = w[y][i][0];
}
if (w[y][i][1] > res2) res2 = w[y][i][1];
y = fa[y][i];
}
if (w[x][0][0] > res1) {
res2 = res1;
res1 = w[x][0][0];
}
if (w[x][0][1] > res2) res2 = w[x][0][1];
if (w[y][0][0] > res1) {
res2 = res1;
res1 = w[y][0][0];
}
if (w[y][0][1] > res2) res2 = w[y][0][1];
asdfasdfasdf = fa[x][0];
return {res1, res2};
}
signed main () {
n = read (), m = read ();
for (int i = 1; i <= n; i ++ ) Fa[i] = i; // 并查集初始化
for (int i = 1; i <= m; i ++ )
e[i].x = read (), e[i].y = read (), e[i].z = read ();
sort (e + 1, e + m + 1);
for (int i = 1; i <= m; i ++ ) { // 最小生成树
int x = get (e[i].x), y = get (e[i].y), z = e[i].z;
if (e[i].x == e[i].y) {
f[i] = 1;
continue;
}
if (x == y) continue;
add (e[i].x, e[i].y, z); // 建树
add (e[i].y, e[i].x, z);
Fa[x] = y;
res += z;
f[i] = 1;
}
dep[1] = 1
dfs (1, 0);
int ans = INF;
for (int i = 1; i <= m; i ++ ) { // 枚举每一条边,让它成为最小生成树的一边。为了严格次大,所以去掉树中最大的边,换上这条边
if (f[i]) continue;
PP asdf = query (e[i].x, e[i].y);
int s1 = asdf.first, s2 = asdf.second;
if (s1 != e[i].z) ans = min (ans, res - s1 + e[i].z);
else ans = min (ans, res - s2 + e[i].z);
}
cout << ans << endl;
return 0;
}