看见某大佬在做,决定补一发题解$qwq$
首先跑出最大生成树(注意有可能不连通),然后我们要求的就是树上两点间路径上的最小边权。 我们用倍增的思路跑出来$w[u][j]$,表示$u$与的它$2^j$的祖先路径上的最小边权(其实是为了配合$lca$),然后求$lca$时顺便记一下最小边权。
码风清奇别在意是之前写的
#include<cstdio> #include<iostream> #include<cstring> #include<cmath> #include<algorithm> #define R register int using namespace std; namespace jack { #define N 100010 #define M 500010 #define Inf 0x3f3f3f3f int n,m,q,cnt,lim,fir[N],dep[N],f[N][20],w[N][20],fa[N]; bool vis[N]; struct Edge { int u,v,w; bool operator < (const Edge& y)const{return w>y.w;} }E[M]; struct edge {int v,w,nxt;}e[M]; inline int g() { R ret=0,fix=1; register char ch; while(!isdigit(ch=getchar())) fix=ch=='-'?-1:fix; do ret=(ret<<3)+(ret<<1)+(ch^48); while(isdigit(ch=getchar())); return ret*fix; } //inline int min(int a,int b) {return a<b?a:b;} inline void add(int u,int v,int w) {e[++cnt].v=v,e[cnt].w=w,e[cnt].nxt=fir[u],fir[u]=cnt;} int getf(int x) {return x==fa[x]?x:fa[x]=getf(fa[x]);} inline bool merge(int u,int v) { R uf=getf(u),vf=getf(v); if(uf==vf) return true; fa[uf]=vf; return false; } inline void kruskal() { sort(E+1,E+m+1); for(R i=1;i<=n;i++) fa[i]=i; for(R i=1,u=E[i].u,v=E[i].v,w=E[i].w;i<=m;i++,u=E[i].u,v=E[i].v,w=E[i].w) if(!merge(u,v)) {add(u,v,w),add(v,u,w);} } void dfs(int u) { vis[u]=true; for(R i=fir[u];i;i=e[i].nxt) { R v=e[i].v; if(dep[v]) continue; dep[v]=dep[u]+1;f[v][0]=u,w[v][0]=e[i].w; for(R j=1,fa=u;f[fa][j];j++) f[v][j+1]=f[fa][j],fa=f[fa][j]; dfs(v); } } inline int lca(int u,int v) { if(getf(u)!=getf(v)) return -1; R ans=Inf; if(dep[u]<dep[v]) swap(u,v); for(R i=lim;i>=0;i--) if(dep[f[u][i]]>=dep[v]) ans=min(ans,w[u][i]),u=f[u][i]; if(u==v) return ans; for(R i=lim;i>=0;i--) if(f[u][i]!=f[v][i]) ans=min(ans,min(w[u][i],w[v][i])),u=f[u][i],v=f[v][i]; return min(ans,min(w[u][0],w[v][0])); } void main() { n=g(),m=g(); lim=log2(n)+1; for(R i=1;i<=m;i++) {E[i].u=g(),E[i].v=g(),E[i].w=g();} kruskal(); for(R i=1;i<=n;i++) if(!vis[i]) {dep[i]=1;dfs(i);f[i][0]=i,w[i][0]=Inf;} for(R i=1;i<=lim;i++) for(R j=1;j<=n;j++) { f[j][i]=f[f[j][i-1]][i-1]; w[j][i]=min(w[j][i-1],w[f[j][i-1]][i-1]); } q=g(); for(int i=1; i<=q; i++) {R u=g(),v=g(); printf("%d\n",lca(u,v));} } } signed main() {jack::main();}