Test instructions: The value of the smallest spanning tree that contains each edge (no self-loop, no heavy edges) in a non-graph unicom
Analysis: Finding the smallest spanning tree of this graph, using the edges of the minimum spanning tree to build the graph
There are two cases for each edge
1: The Edge is the edge on the smallest spanning tree, so the answer is clearly
2: The edge is not on the minimum spanning tree, then the path query, assuming the addition of this edge, then the formation of a ring, delete the ring in addition to the maximum weight outside the edge, forming a tree
The weight of the tree is the answer. (does not need to really join this side)
Note: In fact, with the tree chain and LCA can be, choose their familiar writing on the line, I wrote the tree chain split
#include <cstdio>#include<cstring>#include<algorithm>#include<iostream>#include<cstdlib>#include<cmath>using namespaceStd;typedefLong LongLL;Const intmaxn=200005;intn,m; LL MST;structedge{intW,v,next;} EDGE[MAXN<<1];structe{intU,v,w,id,mark; voidInitintAintBintCintd) {u=a,v=b,w=c,id=d,mark=0; }} O[MAXN];BOOLCmp1 (E a,e b) {returna.id<b.id;}BOOLCMP2 (E a,e b) {returna.w<B.W;}inthead[maxn],p;voidAddedge (intUintVintW) {EDGE[P].V=v; EDGE[P].W=W; Edge[p].next=Head[u]; Head[u]=p++;}intFA[MAXN],SZ[MAXN],ID[MAXN],DEP[MAXN],TOP[MAXN],SON[MAXN],CLK;intWW[MAXN],RE[MAXN];voidDFS1 (intUintFintd) {Fa[u]=F; Sz[u]=1; Son[u]=-1; Dep[u]=D; for(intI=head[u]; ~i; I=Edge[i].next) { intv=edge[i].v; if(v==f)Continue; DFS1 (V,u,d+1); Sz[u]+=Sz[v]; if(son[u]==-1|| Sz[v]>Sz[son[u]]) Son[u]=v,re[u]=EDGE[I].W; }}voidDFS2 (intUintTpintcc) {Id[u]=++CLK; Top[u]=TP; Ww[id[u]]=cc; if(son[u]!=-1) DFS2 (Son[u],tp,re[u]); for(intI=head[u]; ~i; I=Edge[i].next) { intv=edge[i].v; if(v==son[u]| | V==fa[u])Continue; DFS2 (V,V,EDGE[I].W); }}intmaxw[maxn<<2];voidPushup (intRT) {Maxw[rt]=max (maxw[rt*2],maxw[rt*2+1]);}voidBuildintRtintLintR) { if(l==R) {Maxw[rt]=Ww[l]; return; } intM= (l+r) >>1; Build (Rt*2, l,m); Build (Rt*2+1, m+1, R); Pushup (RT);}intQueryintRtintLintRintXinty) { if(x<=l&&r<=y)returnMaxw[rt]; intM= (l+r) >>1; intans=-1; if(x<=m) Ans=max (Ans,query (rt*2, l,m,x,y)); if(y>m) Ans=max (Ans,query (rt*2+1, m+1, r,x,y)); returnans;}intGetans (intUintv) { intans=-1; while(top[u]!=Top[v]) { if(dep[top[u]]<Dep[top[v]) swap (U,V); Ans=max (Ans,query (1,1, N,id[top[u]],id[u])); U=Fa[top[u]]; } if(dep[u]>Dep[v]) swap (U,V); Ans=max (Ans,query (1,1, N,id[son[u]],id[v])); returnans;}intFAT[MAXN];intFindintx) { if(X==fat[x])returnx; returnfat[x]=find (Fat[x]);}voidinit () { for(intI=1; i<=n; ++i) fat[i]=i; MST=p=clk=0; memset (Head,-1,sizeof(head));}intMain () { while(~SCANF ("%d%d",&n,&m)) {init (); for(intI=0; i<m; ++i) {intu,v,w; scanf ("%d%d%d",&u,&v,&W); O[i].init (U,v,w,i); } sort (O,o+M,CMP2); intCnt=0; for(intI=0; i<m; ++i) {intfx=find (O[I].U); intfy=find (O[I].V); if(FY==FX)Continue; Addedge (O[I].U,O[I].V,O[I].W); Addedge (O[I].V,O[I].U,O[I].W); CNT++; O[i].mark=1; FAT[FY]=FX; MST+=O[I].W; if(cnt>=n-1) Break; } DFS1 (1,-1,1); DFS2 (1,1,0); Build (1,1, N); Sort (O,o+M,CMP1); for(intI=0; i<m; ++i) {if(O[i].mark) printf ("%i64d\n", MST); Else { inttt=Getans (O[I].U,O[I].V); printf ("%i64d\n", mst-tt+O[I].W); } } } return 0;}View Code
Educational codeforces Round 3 E (609E) Minimum spanning tree for each edge