input
第一行包含两个整数N 和M,表示无向图的点数与边数。
接下来 M行,每行 3个数x y z 表示,点 x 和点y之间有一条边,边的权值为z。
output
包含一行,仅一个数,表示严格次小生成树的边权和。
example
input
5 6
1 2 1
1 3 2
2 4 3
3 5 4
3 4 3
4 5 6
output
11
思想
1.先用 kruskal 法求最小生成树
2. 然后记录在最小生成树中的每一条路径的最小值及次小值 (不存在= - 1) 可以利用LCA的倍增算法来维护
3. 考虑 i->f[ i ][ j ]与f[ i ][ j ]->f[ f[ i ][ j ] ][ j ]
4. 考虑这两段的最大值相同与不同情况,相同则说明次大值是这两个的次大值的最大值,不同的话,假设(a,b),(c,d)表示两段的(最大,次大),若a>c,显然次大为max(b,c), c>a的情况类似
5. 预处理完,维护沿单链向上跳,记单链的 ( 最大,次大 )为(a,b),当前得到最优值(x,y) , 分三种情况讨论,x与a的大小关系.
#include<bits/stdc++.h>
using namespace std;
int head[100010],cnt,vis[1000010],f[1000010],s[100010][20],d[100010],g[100010][20],h[100010][20];
struct node
{
int to,w,next;
} a[1000010];
struct line
{
int u,v,w;
} b[1000010];
bool cmp(line x,line y)
{
return x.w<y.w;
}
int find(int x)
{
return f[x]==x?x:f[x]=find(f[x]);
}
void add(int u,int v,int w)
{
cnt++;
a[cnt].to=v;
a[cnt].w=w;
a[cnt].next=head[u];
head[u]=cnt;
}
void ddd(int u,int fa)
{
s[u][0]=fa;
d[u]=d[fa]+1;
for(int i=head[u]; i!=-1; i=a[i].next)
{
int v=a[i].to;
if(v==fa) continue;
g[v][0]=a[i].w;
h[v][0]=-1;
ddd(v,u);
}
}
void sol_1(int &x,int &y,int z,int d,int e,int f)
{
if(z==e)
{
x=z;
y=max(d,f);
return;
}
if(z>e)
{
swap(z,e);
swap(d,f);
}
x=e;
y=max(z,f);
}
int sol_2(int x,int y,int w)
{
if(w==x) return w-y;
return w-x;
}
void sol_3(int &x,int &y,int u,int t)
{
if(g[u][t]==x) y=max(y,h[u][t]);
else if(g[u][t]<x) y=max(y,g[u][t]);
else
{
y=(x,h[u][t]);
x=g[u][t];
}
}
int sol(int u,int v,int w)
{
int x=-1,y=-1,dis,t=0;
if(d[u]<d[v]) swap(u,v);
dis=d[u]-d[v];
while(dis>0)
{
if(dis&1)
{
sol_3(x,y,u,t);
u=s[u][t];
}
t++;
dis=dis>>1;
}
if(u==v) return sol_2(x,y,w);
for(int i=18; i>=0; i--)
{
if(s[u][i]!=s[v][i])
{
sol_3(x,y,u,i);
sol_3(x,y,v,i);
u=s[u][i];
v=s[v][i];
}
}
sol_3(x,y,u,0);
sol_3(x,y,v,0);
return sol_2(x,y,w);
}
int main()
{
int i,n,m,tot=0,u,v,uu,vv,j;
long long ans=0;
cnt=0;
scanf("%d%d",&n,&m);
memset(head,-1,sizeof(head));
memset(vis,0,sizeof(vis));
for(i=1; i<=m; i++)
scanf("%d%d%d",&b[i].u,&b[i].v,&b[i].w);
sort(b+1,b+1+m,cmp);
for(i=1; i<=n; i++) f[i]=i;
for(i=1; i<=m; i++)
{
u=b[i].u;
v=b[i].v;
uu=find(u);
vv=find(v);
if(uu==vv) continue;
f[uu]=vv;
vis[i]=1;
add(u,v,b[i].w);
add(v,u,b[i].w);
ans+=b[i].w;
tot++;
if(tot==n-1) break;
}
ddd(1,0);
for(j=0; j<18; j++)
{
for(i=1; i<=n; i++)
{
if(s[i][j]==0) s[i][j+1]=0;
else
{
s[i][j+1]=s[s[i][j]][j];
sol_1(g[i][j+1],h[i][j+1],g[i][j],h[i][j],g[s[i][j]][j],h[s[i][j]][j]);
}
}
}
u=0x3f3f3f3f;
for(i=1; i<=m; i++)
if(!vis[i]) u=min(u,sol(b[i].u,b[i].v,b[i].w));
printf("%lld",ans+u);
return 0;
}