严格次小生成树
1.先求出最小生成树
2.枚举不在最小生成树上的每一条边,加入最小生成树构成环
3.每个环上找到原来最小生成树上的最长的边和次长的边
4.如果最长的边小于新加的边,将最长边去掉,否则去掉次长的边,如果次长的边等于最长的边,不存在严格次小生成树.
5.求权值
非严格次小生成树只需要找到原来最小生成树上的最长的边去掉即可,允许出现结果权值与最小生成树相同.
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
typedef long long ll;
const int N=2e5+10,M=3e5+10;
const ll inf=1e18;
int con=1,h[N],nex[2*M],to[2*M],par[N][17],lg[N],vis[N],p[N],s[M],use[M];
ll w[2*M],d[N],max1[N][32],max2[N][32];
struct edge
{
int c,t;
ll v;
edge(int x,int y,ll z):c(x),t(y),v(z){}
};
vector<edge>e;
void add(int x,int y,ll z)
{
nex[con]=h[x];
h[x]=con;
to[con]=y;
w[con++]=z;
}
ll find(int x)
{return p[x]=p[x]==x?x:find(p[x]);}
bool cmp(int x,int y)
{
return e[x].v<e[y].v;
}
ll kruskal()
{
ll res=0;
for(int i=0;i<(int)e.size();i++)
{
int x=find(e[s[i]].c),y=find(e[s[i]].t);
if(x==y)
continue;
use[s[i]]=1;
add(e[s[i]].c,e[s[i]].t,e[s[i]].v);
add(e[s[i]].t,e[s[i]].c,e[s[i]].v);
p[y]=x;
res+=e[s[i]].v;
}
return res;
}
void calmax1max2(ll a1,ll b1,ll c1,ll d1,ll &x,ll &y)
{
if(a1>c1)
{
x=a1;
y=max(c1,b1);
}
else if(a1==c1)
{
x=a1;
y=max(b1,d1);
}
else
{
x=c1;
y=max(a1,d1);
}
}
queue<int>q;
void bfs(int x,int deep)
{
q.push(x);
d[x]=0;
while(!q.empty())
{
x=q.front();q.pop();
for(int i=1;i<=lg[d[x]];++i)
{
par[x][i]=par[par[x][i-1]][i-1];
calmax1max2(max1[x][i-1],max2[x][i-1],max1[par[x][i-1]][i-1],max2[par[x][i-1]][i-1],max1[x][i],max2[x][i]);
}
for(int i=h[x];i;i=nex[i])
{
if(vis[to[i]])
continue;
vis[to[i]]=1;
par[to[i]][0]=x;
max1[to[i]][0]=w[i];
max2[to[i]][0]=-inf;
d[to[i]]=d[x]+1;
q.push(to[i]);
}
}
}
void lca(int x,int y,ll &h1,ll &k1)
{
if(d[x]<d[y])
swap(x,y);
ll m1,m2,m3,m4;
m1=m2=m3=m4=-inf;
int check=0;
while(d[x]>d[y])
{
check++;
if(check==50)
break;
int mid=d[x]-d[y];
calmax1max2(m1,m2,max1[x][lg[mid]],max2[x][lg[mid]],m1,m2);
x=par[x][lg[mid]];
}
if(x==y)
{
calmax1max2(m1,m2,m3,m4,h1,k1);
return;
}
for(int i=lg[d[x]];i>=0;--i)
{
if(par[x][i]!=par[y][i])
{
calmax1max2(m1,m2,max1[x][i],max2[x][i],m1,m2);
calmax1max2(m3,m4,max1[y][i],max2[y][i],m3,m4);
x=par[x][i];
y=par[y][i];
}
}
calmax1max2(m1,m2,max1[x][0],max2[x][0],m1,m2);
calmax1max2(m3,m4,max1[y][0],max2[y][0],m3,m4);
calmax1max2(m1,m2,m3,m4,h1,k1);
}
int main()
{
int n,m;cin>>n>>m;
for(int i=0;i<m;++i)
{
int x,y;
ll z;
scanf("%d%d%lld",&x,&y,&z);
if(x==y)
continue;
e.push_back(edge(x,y,z));
}
for(int i=0;i<=n;++i)
p[i]=i;
for(int i=0;i<(int)e.size();++i)
s[i]=i;
int tmp=e.size();
sort(s,s+tmp,cmp);
ll ans=kruskal();
for(int i=2;i<=n;++i)
lg[i]=(i&(i-1))==0?lg[i-1]+1:lg[i-1];
vis[1]=1;
bfs(1,0);
ll se=1e16;
for(int i=0;i<(int)e.size();++i)
{
if(use[i])
continue;
ll m1=0,m2=0;
lca(e[i].c,e[i].t,m1,m2);
if(m1<e[i].v)
se=min(se,ans+e[i].v-m1);
else if(m2!=-inf)
se=min(se,ans+e[i].v-m2);
}
cout<<se<<endl;
return 0;
}