今天又把次小生成树写了一遍 收获还是挺大的
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
#define inf 1e15 + 7
#define RE register
using namespace std ;
inline int read() {
int x = 0,f = 1;char k = getchar() ;
while(k < '0'||k > '9'){if(k == '-')f = -1;k = getchar() ;}
while(k >= '0'&&k <= '9') {x = x * 10 + k - '0';k = getchar() ;}
return x * f;
}
const LL maxn = 100005;
const LL maxm = 300005 ;
int head[maxn],TOP,n,m,Father[maxn];
LL sum ;
struct Graph {int fro,end,value;}g[maxm];
struct Edge {int to,next,value;}e[maxm << 1];
LL find(int x) {
if(x == Father[x]) return Father[x] ;
return Father[x] = find(Father[x]) ;
}
bool book[maxm];
bool CMP(Graph x,Graph y) {return x.value < y.value ;} /* ********* 少了return*/
void add_edge(int u,int v,int w) {
e[++TOP].to = v;
e[TOP].next = head[u];
e[TOP].value = w;
head[u] = TOP ;
}
void Kruscal() {
LL k = 0;
sort(g + 1,g + m + 1,CMP );
for(RE int i = 1;i <= m ;++i) {
LL fx = find(g[i].fro),fy = find(g[i].end) ;
if(fx != fy) {
add_edge(g[i].fro,g[i].end,g[i].value );
add_edge(g[i].end,g[i].fro,g[i].value );
Father[fx] = fy ;++k ;
book[i] = 1;
sum += (LL)g[i].value ;
}
if(k == n - 1) break ;
}
}
LL par[maxn][22],depth[maxn] ;
LL maxx[maxn][22],minn[maxn][22] ;
void dfs(LL u,LL father) {
depth[u] = depth[father] + 1 ;
par[u][0] = father ;
for(RE int i = head[u]; i ;i = e[i].next)
if(father != e[i].to) {
maxx[e[i].to][0] = e[i].value ;
minn[e[i].to][0] = -inf ;
dfs(e[i].to,u) ;
}
}
LL MAX(LL x,LL y) {if(x > y) return x;else return y ;}
LL MIN(LL x,LL y) {if(x < y) return x;else return y ;}
void calc() {
for(RE int j = 1;j <= 20 ;++j)
for(RE int i = 1;i <= n ;++i) {
par[i][j] = par[par[i][j - 1]][j - 1] ;
maxx[i][j] = MAX(maxx[i][j - 1],maxx[par[i][j - 1]][j - 1]) ;
minn[i][j] = MAX(minn[i][j - 1],minn[par[i][j - 1]][j - 1]) ;
if(maxx[i][j - 1] != maxx[par[i][j - 1]][j - 1])
minn[i][j] =
MAX(minn[i][j],min(maxx[par[i][j - 1]][j - 1],maxx[i][j - 1])) ;
}
}
int LCA(int x,int y) {
if(x == y) return x;
if(depth[x] < depth[y]) swap(x,y) ;
for(RE int i = 20;i >= 0 ;--i)
if(depth[par[x][i]] >= depth[y]) x = par[x][i] ;
if(x == y) return x ;
for(RE int i = 20;i >= 0 ;--i)
if(par[x][i] != par[y][i])
x = par[x][i],y = par[y][i] ;
if(x != y) return par[x][0] ;
return x ;
}
LL work(int u,int v,int flag) { // **************** 注意这个函数 LL
LL res = -inf ;
for(RE int i = 20;i >= 0 ;--i)
if(depth[par[u][i]] >= depth[v]) {
if(maxx[u][i] == flag) res = MAX(res,minn[u][i]) ;
else res = MAX(res,maxx[u][i]) ;
u = par[u][i] ;
}
return res ;
}
int main() {
scanf("%d%d",&n,&m) ;
for(RE int i = 1;i <= m ;++i) {
int u = read(),v = read(),w = read() ;
g[i].fro = u;g[i].end = v;g[i].value = w;
}
for(RE int i = 1;i <= n ;++i) Father[i] = i;
Kruscal() ;
dfs(1,0) ; calc() ;
LL ans = inf;
for(RE int i = 1;i <= m ;++i)
if(!book[i]) {
int u = g[i].fro,v = g[i].end ;
LL lca = LCA(u,v) ;
LL l1 = work(u,lca,g[i].value) ,l2 = work(v,lca,g[i].value) ;
ans = MIN(ans , sum + g[i].value - MAX(l1,l2)) ; //怎么加怎么减认真思考!!
}
printf("%lld",ans) ;
return 0;
}```