用lca求出每个非树边的路径中的边的最小值和次小值(因为要求的是严格次小生成树),这里有求次小的经典模板。
#include <iostream>
#include <cstring>
#include <algorithm>
#define LL long long
using namespace std;
const int N = 1e5+10,M=1e6+10,INF=0x3f3f3f3f;
int n,m;
int h[N],e[M],ne[M],idx;
LL w[M];
LL ans = 1e18;
void add(int a, int b, int c) // 添加一条边a->b,边权为c
{
e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++ ;
}
int fa[N][17];
int dist1[N][17],dist2[N][17];
struct Edge{
int a,b;
LL c;
bool used;
bool operator<(const Edge & e)const{
return c<e.c;
}
}edge[M];
int p[N];
int find(int x){
if(p[x]!=x)p[x]=find(p[x]);
return p[x];
}
int q[N];
int dep[N];
void bfs(int u){
memset(dep,0x3f,sizeof dep);
dep[0]=0,dep[1]=1;
int hh=0,tt=0;
q[0]=1;
while(hh<=tt){
int t=q[hh++];
for(int v=h[t];~v;v=ne[v]){
int k=e[v];
if(dep[k]>dep[t]+1){
q[++tt]=k;
dep[k]=dep[t]+1;
fa[k][0]=t;
for(int i=1;i<17;i++)fa[k][i]=fa[fa[k][i-1]][i-1];
dist1[k][0]=w[v];
//k 往上跳i步 的最大值 次大值
for(int i=1;i<17;i++){
int distance[4]={dist1[k][i-1],dist2[k][i-1],dist1[fa[k][i-1]][i-1],dist2[fa[k][i-1]][i-1]};
for(int j=0;j<4;j++){
int d=distance[j];
if(d>dist1[k][i])dist2[k][i]=dist1[k][i],dist1[k][i]=d;
else if(d!=dist1[k][i]&&d>dist2[k][i])dist2[k][i]=d;
}
}
}
}
}
}
int query(int a,int b, int up){
int ma1=-INF,ma2=-INF;
static int tmp[2*N];
int cnt=0;
if(dep[a]<dep[b])swap(a,b);
for(int i=16;i>=0;i--)
if(dep[fa[a][i]]>=dep[b]){
tmp[cnt++]=dist1[a][i];
tmp[cnt++]=dist2[a][i];
a=fa[a][i];
}
if(a!=b){
for(int i=16;i>=0;i--){
if(fa[a][i]!=fa[b][i]){
tmp[cnt++]=dist1[a][i];
tmp[cnt++]=dist2[a][i];
tmp[cnt++]=dist1[b][i];
tmp[cnt++]=dist2[b][i];
a=fa[a][i];
b=fa[b][i];
}
}
tmp[cnt++]=dist1[a][0];
tmp[cnt++]=dist2[a][0];
tmp[cnt++]=dist1[b][0];
tmp[cnt++]=dist2[b][0];
}
for(int i=0;i<cnt;i++){
int e=tmp[i];
if(e>ma1)ma2=ma1,ma1=e;
else if(e!=ma1&&e>ma2)ma2=e;
}
if(up>ma1)return ma1;
else if(up==ma1)return ma2;
}
int main(){
cin.tie(0);
memset(h, -1, sizeof h);
for(int i=1;i<N;i++)p[i]=i;
cin>>n>>m;
for(int i=0;i<m;i++){
cin>>edge[i].a>>edge[i].b>>edge[i].c;
}
sort(edge,edge+m);
LL res=0;
for(int i=0;i<m;i++){
int a=edge[i].a,b=edge[i].b,c=edge[i].c;
int pa=find(a),pb=find(b);
if(pa!=pb){
edge[i].used=true;
add(a,b,c);
add(b,a,c);
res+=c;
p[pa]=pb;
}
}
memset(dist1,-0x3f,sizeof dist1);
memset(dist2,-0x3f,sizeof dist2);
bfs(1);
for(int i=0;i<m;i++)
if(!edge[i].used)
{
int a=edge[i].a,b=edge[i].b,c=edge[i].c;
ans=min(ans,res-query(a,b,c)+c);
}
cout<<ans;
return 0;
}
浙公网安备 33010602011771号