严格次小生成树
∑
w
次
>
∑
w
最
\sum w_{次}>\sum w_{最}
∑w次>∑w最
建好最小生成树后,改动一下得到
枚举每条非树边,替换树中的最大值
但是由于可能算出来和最小生成树一样,就不是严格的了。于是我们需要维护最大和严格次大。用倍增维护即可
#include<bits/stdc++.h>
#define ll long long
#define int long long
using namespace std;
const int N=1e5+10,M=6e5+10;
const ll INF=1e18;
int n,m;
ll sum,ans;
int head[N],nex[M],to[M],val[M],tot;
void build(int u,int v,int w)
{
tot++;nex[tot]=head[u];to[tot]=v;val[tot]=w;head[u]=tot;
}
struct Road{
int x,y,z;
bool operator < (const Road x)const{
return z<x.z;
}
}a[M];
int f[N],pos[M];
int fa(int x){return x==f[x]?x:f[x]=fa(f[x]);}
void kruscal()
{
for(int i=1;i<=n;i++)f[i]=i;
sort(a+1,a+m+1);
for(int i=1;i<=m;i++)
{
int x=fa(a[i].x),y=fa(a[i].y);
if(x!=y)
{
f[x]=y;sum+=a[i].z;pos[i]=1;
build(a[i].x,a[i].y,a[i].z);
build(a[i].y,a[i].x,a[i].z);
}
}
}
int dep[N],bz[N][20];
ll bm1[N][20],bm2[N][20];
void dfs(int u,int fr)
{
bz[u][0]=fr;dep[u]=dep[fr]+1;
for(int i=head[u];i;i=nex[i])
{
int v=to[i];if(v==fr)continue;
dfs(v,u);bm1[v][0]=bm2[v][0]=val[i];
}
}
ll ls[5];int s;
void updata(ll &g1,ll &g2,ll a1,ll a2,ll a3,ll a4)
{
ls[1]=a1;ls[2]=a2;ls[3]=a3;ls[4]=a4;
sort(ls+1,ls+5);
s=3;while(s&&ls[s]==ls[s+1])s--;
g1=ls[4];g2=ls[s];
}
void get_bz()
{
dfs(1,0);
for(int j=1;j<=18;j++)
for(int i=1;i<=n;i++)
{
bz[i][j]=bz[bz[i][j-1]][j-1];
updata(bm1[i][j],bm2[i][j],bm1[i][j-1],bm1[bz[i][j-1]][j-1],bm2[i][j-1],bm2[bz[i][j-1]][j-1]);
}
}
ll m1,m2;
int lca(int x,int y)
{
m1=0,m2=0;
if(dep[x]<dep[y])swap(x,y);
for(int i=18;i>=0;i--)
if(dep[bz[x][i]]>=dep[y])
{
updata(m1,m2,m1,m2,bm1[x][i],bm2[x][i]);
x=bz[x][i];
}
if(x==y)return x;
for(int i=18;i>=0;i--)
if(bz[x][i]^bz[y][i])
{
updata(m1,m2,m1,m2,bm1[x][i],bm2[x][i]);
updata(m1,m2,m1,m2,bm1[y][i],bm2[y][i]);
x=bz[x][i],y=bz[y][i];
}
updata(m1,m2,m1,m2,bm1[x][0],bm2[x][0]);
updata(m1,m2,m1,m2,bm1[y][0],bm2[y][0]);
return bz[x][0];
}
void get_M2tree()
{
ans=INF;
for(int i=1;i<=m;i++)
{
if(!pos[i])
{
lca(a[i].x,a[i].y);
if(a[i].z!=m1)
ans=min(ans,sum-m1+a[i].z);
ans=min(ans,sum-m2+a[i].z);
}
}
}
signed main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
scanf("%lld%lld%lld",&a[i].x,&a[i].y,&a[i].z);
kruscal();
get_bz();
get_M2tree();
printf("%lld",ans);
}
再次吐槽为什么每次 咕站模板题都会T呀 T^T