Luogu P1967 货车运输
十分经典的LCA题目。最大生成树+倍增LCA
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int read(){
int k=0; char c=getchar();
for(;c<'0'||c>'9';) c=getchar();
for(;c>='0'&&c<='9';c=getchar())
k=(k<<3)+(k<<1)+c-48;
return k;
}
struct zzz{
int f,t,len;
}mst[50010]; int fa[10010];
struct hhh{
int t,len,nex;
}lca[10010<<1]; int head[10010],tot;
void add(int x,int y,int z){
lca[++tot].t=y;
lca[tot].len=z;
lca[tot].nex=head[x];
head[x]=tot;
}
int findd(int x){
return x==fa[x]? x: fa[x]=findd(fa[x]);
}
bool cmp(zzz x,zzz y){
return x.len>y.len;
}
int f[10010][32],deth[10010],lg[10010],maxx[10010][32];
bool vis[10010];
void dfs(int from,int fath){
vis[from]=1;
f[from][0]=fath; deth[from]=deth[fath]+1;
for(int i=1;1<<i<=deth[from];i++){
f[from][i]=f[f[from][i-1]][i-1];
maxx[from][i]=min(maxx[f[from][i-1]][i-1],maxx[from][i-1]);
}
for(int i=head[from];i;i=lca[i].nex)
if(lca[i].t!=f[from][0]){
maxx[lca[i].t][0]=lca[i].len;
dfs(lca[i].t,from);
}
}
int LCA(int x,int y){
int ans=0x7fffffff;
if(deth[x]<deth[y]) swap(x,y);
while(deth[y]<deth[x]){
ans=min(ans,maxx[x][lg[deth[x]-deth[y]]-1]);
x=f[x][lg[deth[x]-deth[y]]-1];
}
if(x==y) return ans;
for(int i=lg[deth[x]];i>=0;i--)
if(f[x][i]!=f[y][i]){
ans=min(ans,min(maxx[x][i],maxx[y][i]));
x=f[x][i],y=f[y][i];
}
return min(ans,min(maxx[x][0],maxx[y][0]));
}
int main(){
memset(maxx,127,sizeof(maxx));
int n=read(),m=read();
for(int i=1;i<=n;i++)
fa[i]=i;
for(int i=1;i<=m;i++)
mst[i].f=read(),mst[i].t=read(),mst[i].len=read();
sort(mst+1,mst+m+1,cmp);
int tot=0;
for(int i=1;i<=m;i++){
int x=findd(mst[i].f),y=findd(mst[i].t);
if(x!=y){
fa[x]=y;
add(mst[i].f,mst[i].t,mst[i].len);
add(mst[i].t,mst[i].f,mst[i].len);
tot++;
}
if(tot==n-1) break;
}
for(int i=1;i<=n;i++)
lg[i]=lg[i-1]+(1<<lg[i-1]==i);
for(int i=1;i<=n;i++){
if(!vis[i])
dfs(i,0);
}
int q=read();
for(int i=1;i<=q;i++){
int x=read(),y=read();
if(findd(x)!=findd(y)){
printf("-1\n"); continue;
}
else printf("%d\n",LCA(x,y));
}
return 0;
}