重构树的版子题,当然也可以用倍增或二分答案。
看代码:
#include<bits/stdc++.h> using namespace std; const int maxn=1e6+10; struct node{ int x,y,z; }edge[maxn]; int n,m,q,cnt; inline int read(){ int x=0,f=1;char c=getchar(); while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-'0';c=getchar();} return x*f; } inline int cmp(node x,node y){ return x.z>y.z; } int fa[maxn],f[maxn],val[maxn]; inline int find1(int x){ if(x==fa[x])return x; return fa[x]=find1(fa[x]); } inline int find2(int x){ if(x==f[x])return x; return f[x]=find2(f[x]); } int beg[maxn],nex[maxn],to[maxn],e; inline void add(int x,int y){ e++;nex[e]=beg[x]; beg[x]=e;to[e]=y; } int dep[maxn],ff[maxn][20]; inline void dfs(int x,int anc){ dep[x]=dep[anc]+1; ff[x][0]=anc; for(int i=1;i<=19;i++) ff[x][i]=ff[ff[x][i-1]][i-1]; for(int i=beg[x];i;i=nex[i]) if(to[i]!=anc)dfs(to[i],x); } inline int lca(int x,int y){ if(dep[x]<dep[y])swap(x,y); for(int i=19;i>=0;i--) if(dep[x]-(1<<i)>=dep[y]) x=ff[x][i]; if(x==y)return x; for(int i=19;i>=0;i--) if(ff[x][i]!=ff[y][i]){ x=ff[x][i]; y=ff[y][i]; } return ff[x][0]; } int main(){ cnt=n=read();m=read(); for(int i=1;i<=m;i++){ edge[i].x=read(); edge[i].y=read(); edge[i].z=read(); } sort(edge+1,edge+1+m,cmp); for(int i=1;i<=2*n;i++) fa[i]=f[i]=i; int x,y; for(int i=1;i<=m;i++){ x=edge[i].x,y=edge[i].y; if(find1(x)!=find1(y)){ cnt++; val[cnt]=edge[i].z; add(cnt,find2(x)); add(find2(x),cnt); add(cnt,find2(y)); add(find2(y),cnt); //printf("%d %d %d ",cnt,find2(x),find2(y)); f[find2(x)]=f[find2(y)]=cnt; fa[find1(x)]=find1(y); } } for(int i=1;i<=cnt;i++) if(f[i]==i)dfs(i,0); q=read(); for(int i=1;i<=q;i++){ x=read(),y=read(); if(find1(x)!=find1(y))puts("-1"); else printf("%d ",val[lca(x,y)]); } return 0; }
深深地感到自己的弱小。