In an undirected graph connection, find the value of the minimum spanning tree containing each edge (no self ring, no double edge)
Analysis: find the minimum spanning tree of this graph, and use the edge building graph on the minimum spanning tree
For each side, there are no more than two cases
1: This edge is the edge on the minimum spanning tree, so the answer is obvious
2: If the edge is not on the minimum spanning tree, then carry out path query. If the edge is added, a ring will be formed. Delete the maximum weight edge on the ring except the edge to form a tree
The weight of the tree is the answer. (you don't really need to join this side)
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=201000;
const int inf=0x3f3f3f3f;
int visedge[maxn];
struct edge
{
int v,nxt;
long long w;
}edge[maxn*3+100];
int head[maxn],cnt=0;
void add_edge(int u,int v,int w)
{
edge[cnt].v=v;
edge[cnt].w=w;
edge[cnt].nxt=head[u];
head[u]=cnt++;
}
struct node
{
int x,y,z;
int id;
}a[maxn*3+100],b[maxn*3+100];
int deg[maxn],fa[maxn][20];
long long dis[maxn][20];
int vis[maxn];
void bfs(int u)
{
queue<int>q;
q.push(u);
vis[u]=1;
fa[u][0]=u;
deg[u]=0;
while(!q.empty())
{
int now=q.front();
vis[now]=1;
q.pop();
for(int i=1;i<20;i++)
{
fa[now][i]=fa[fa[now][i-1]][i-1];
dis[now][i]=max(dis[now][i-1],dis[fa[now][i-1]][i-1]);
}
for(int i=head[now];i!=-1;i=edge[i].nxt)
{
int to=edge[i].v;
if(to==fa[now][0])
{
continue;
}
deg[to]=deg[now]+1;
dis[to][0]=edge[i].w;
fa[to][0]=now;
q.push(to);
}
}
}
int lca(int u,int v)
{
if(deg[u]>deg[v])
{
swap(u,v);
}
int hu=deg[u],hv=deg[v];
int tu=u,tv=v;
for(int det=hv-hu,i=0;det;det>>=1,i++)
{
if(det&1)
{
tv=fa[tv][i];
}
}
if(tu==tv)
return tu;
for(int i=19;i>=0;i--)
{
if(fa[tu][i]==fa[tv][i])
continue;
tu=fa[tu][i];
tv=fa[tv][i];
}
return fa[tu][0];
}
int cmp(node aa,node bb)
{
return aa.z<bb.z;
}
int pre[maxn];
int findd(int x)
{
int r=x;
while(r!=pre[r])
r=pre[r];
int i=x,j;
while(i!=r)
{
j=pre[i];
pre[i]=r;
i=j;
}
return r;
}
long long solve(int u,int v)
{
long long maxx=0;
int hu=deg[u],hv=deg[v];
int tu=u,tv=v;
for(int det=hu-hv,i=0;det;det>>=1,i++)
{
if(det&1)
{
maxx=max(maxx,dis[tu][i]);
tu=fa[tu][i];
}
}
return maxx;
}
int main ()
{
memset(head,-1,sizeof(head));
cnt=0;
memset(deg,0,sizeof(deg));
memset(fa,0,sizeof(fa));
int m,n;
cin>>n>>m;
for(int i=1;i<=m;i++)
{
scanf("%d%d%lld",&a[i].x,&a[i].y,&a[i].z);
b[i].x=a[i].x;
b[i].y=a[i].y;
b[i].z=a[i].z;
a[i].id=i;
}
for(int i=1;i<=n;i++)
{
pre[i]=i;
}
sort(a+1,a+1+m,cmp);
int nn=0;
long long sum=0;
for(int i=1;i<=m;i++)
{
int tx,ty;
tx=findd(a[i].x);
ty=findd(a[i].y);
if(tx!=ty)
{
visedge[a[i].id]=1;
pre[ty]=tx;
sum+=a[i].z;
add_edge(a[i].x,a[i].y,a[i].z);
add_edge(a[i].y,a[i].x,a[i].z);
nn++;
if(nn==n-1)
{
break;
}
}
}
for(int i=1;i<=n;i++)
{
if(!vis[i])
{
bfs(i);
}
}
for(int i=1;i<=m;i++)
{
if(visedge[i]==0)
{
int xx=b[i].x;
int yy=b[i].y;
int aa=lca(xx,yy);
//printf("\n%d %d %d %d\n",xx,yy,solve(xx,aa),solve(yy,aa));
printf("%lld\n",sum-max(solve(xx,aa),solve(yy,aa))+b[i].z);
}
else
{
printf("%lld\n",sum);
}
}
}