It's basically the same as last year Noip a problem.
After the smallest spanning tree, it becomes the most weighted edge on the path that asks for a connection to two points.
Multiply LCA, profile or whatever.
Block trees are also very simple, but the point of each point to be recorded as a "connection with its parent node of the weight", and then do not use the LCA value of a violent LCA to update the answer.
1#include <cmath>2#include <cstdio>3#include <cstring>4#include <algorithm>5 using namespacestd;6 #defineMAXN 150017 intRes,num;Charc,ch[ -];8InlineintGe ()9 {Tenres=0; C='*'; One while(c<'0'|| C>'9') c=GetChar (); A while(c>='0'&&c<='9') {res=res*Ten+ (C-'0'); C=GetChar ();} - returnRes; - } theInlinevoidPintx) - { -num=0;if(!x) {Putchar ('0');p UTS ("");return;} - while(x>0) ch[++num]=x%Ten, x/=Ten; + while(Num) Putchar (ch[num--]+ -); -Putchar ('\ n'); + } A structedge{intU,v,w;voidRead () {u=ge (); V=ge (); w=Ge ();}}; at BOOLcmpConstEdge &a,ConstEdge &b) {returna.w<B.W;} -Edge edges[maxn<<1]; - structGraph - { - intv[maxn<<1],first[maxn<<1],next[maxn<<1],w[maxn<<1],en; - voidAddedge (Const int&a,Const int&b) in{v[++en]=b;next[en]=first[a];first[a]=en;} - voidAddedge (Const int&a,Const int&b,Const int&c) to{v[++en]=b;w[en]=c;next[en]=first[a];first[a]=en;} + }; -Graph g[2]; the intFA[MAXN],DEP[MAXN],TOP[MAXN],SIZ[MAXN],SZ,MAXV[MAXN],W[MAXN]; * intn,m,q,x,y; $ voidMakeblock (intcur)Panax Notoginseng { - for(inti=g[0].first[cur];i;i=g[0].next[i]) the if(g[0].v[i]!=Fa[cur]) + { Adep[g[0].v[i]]=dep[cur]+1; thew[g[0].v[i]]=g[0].w[i]; +fa[g[0].v[i]]=cur; - if(siz[top[cur]]<sz) $ { $siz[top[cur]]++; -top[g[0].v[i]]=Top[cur]; -g[1]. Addedge (cur,g[0].v[i]); the } -Makeblock (g[0].v[i]);Wuyi } the } - intRANK[MAXN],FATHER[MAXN]; Wu voidInit () { for(intI=1; i<=n;i++) father[i]=i;} - intFindrootintx) About { $ if(father[x]==x)returnx; - intrt=Findroot (father[x]); -father[x]=RT; - returnRT; A } + voidUnion (intUintV) the { - if(Rank[u]<rank[v]) father[u]=V; $ Else the { thefather[v]=U; the if(Rank[u]==rank[v]) rank[u]++; the } - } in voidDfsintCurintMaxnow) the { themaxv[cur]=Maxnow; About for(inti=g[1].first[cur];i;i=g[1].next[i]) theDFS (g[1].v[i],max (maxnow,w[g[1].v[i])); the } the intQuery_max (intUintv) + { - intres=-2147483647; the while(u!=v)Bayi { the if(top[u]==Top[v]) the { - if(dep[u]<Dep[v]) swap (U,V); -res=Max (Res,w[u]); theu=Fa[u]; the } the Else the { - if(dep[top[u]]<Dep[top[v]) swap (U,V); theres=Max (Res,maxv[u]); theu=Fa[top[u]]; the }94 } the returnRes; the } the intMain ()98 { AboutN=ge (); M=ge (); q=Ge (); - for(intI=1; i<=m;i++) Edges[i]. Read ();101Sort (edges+1, edges+m+1, CMP);102 init ();103 intCnt=0;104 for(intI=1; i<=m;i++) the {106 intF1=findroot (edges[i].u), f2=Findroot (EDGES[I].V);107 if(f1!=F2)108 {109 Union (F1,F2); theg[0]. Addedge (EDGES[I].U,EDGES[I].V,EDGES[I].W);111g[0]. Addedge (EDGES[I].V,EDGES[I].U,EDGES[I].W); thecnt++;113 if(cnt==n-1) Break; the } the } thesz=sqrt (n);117 for(intI=1; i<=n;i++)118 {119top[i]=i; -siz[i]=1;121 }122Makeblock (1);123 for(intI=1; i<=n;i++)if(top[i]==i) DFS (i,w[i]);124 for(intI=1; i<=q;i++) {X=ge (); y=Ge (); P (Query_max (x, y));} the return 0;126}
"Kruscal" "minimum Spanning Tree" "Block Tree" bzoj3732 Network