题目原址在下面:
题目大意:n个点m条边每次询问两点之间路径的最小值的最大值。
思路:先跑一遍Kruskal,将边权从大到小排序,然后选n-1条边。之后跑倍增LCA。
#include<bits/stdc++.h>
using namespace std;
const int P=30;
struct nob{
int sta,ed,val,jump;
}a[2000001],b[2000001];
int n,m,num=0,f[1000001],tot=0,jump[1000001]={0},fa[1000001][30],root;
int deep[1000001],qe,mina[1000001][30];
bool judge[1000001]={0};
bool mmp(nob a,nob b){
return a.val>b.val;
}
void add(int sta,int ed,int val){
num++;
a[num].sta=sta;
a[num].ed=ed;
a[num].val=val;
}
void ad(int sta,int ed,int val){
tot++;
b[tot].sta=sta;
b[tot].ed=ed;
b[tot].val=val;
b[tot].jump=jump[sta];
jump[sta]=tot;
}
int find(int x){
if (x==f[x]) return x;
f[x]=find(f[x]);
return f[x];
}
void dfs(int pos){
judge[pos]=true;
for (int i=jump[pos]; i; i=b[i].jump){
if (!judge[b[i].ed]){
fa[b[i].ed][0]=pos;
mina[b[i].ed][0]=b[i].val;
deep[b[i].ed]=deep[pos]+1;
// judge[a[i].ed]=1;
dfs(b[i].ed);
}
}
}
void bz(){
for (int i=1; i<P; i++){
for (int l=1; l<=n; l++){
fa[l][i]=fa[fa[l][i-1]][i-1];
mina[l][i]=min(mina[l][i-1],mina[fa[l][i-1]][i-1]);
}
}
}
int LCA(int x,int y){
int rem=1e9;
if (deep[x]<deep[y])
swap(x,y);
int d=deep[x]-deep[y];
for (int i=0; i<P; i++)
if ((1<<i)&d){
rem=min(rem,mina[x][i]);
x=fa[x][i];
}
if (x==y) return rem;
for (int i=P-1; i>=0; i--){
if (fa[x][i]!=fa[y][i]){
rem=min(rem,mina[x][i]);
rem=min(rem,mina[y][i]);
x=fa[x][i];
y=fa[y][i];
}
}
rem=min(rem,mina[x][0]);
rem=min(rem,mina[y][0]);
return rem;
}
int main(){
scanf("%d%d",&n,&m);
for (int i=1,x,y,val; i<=m; i++){
scanf("%d%d%d",&x,&y,&val);
add(x,y,val);
add(y,x,val);
}
sort(a+1,a+1+num,mmp);
for (int i=1; i<=n; i++)
f[i]=i;
for (int i=1; i<=num; i++){
if (find(a[i].sta)!=find(a[i].ed)){
f[find(a[i].sta)]=find(a[i].ed);
ad(a[i].sta,a[i].ed,a[i].val);
ad(a[i].ed,a[i].sta,a[i].val);
}
}
for (int i=1; i<=n; i++){
if (f[i]==i){
deep[i]=1;
judge[i]=true;
dfs(i);
}
}
bz();
scanf("%d",&qe);
for (int i=1,x,y; i<=qe; i++){
cin>>x>>y;
if (find(x)!=find(y)){
printf("-1
");
continue;
}
printf("%d
",LCA(x,y));
}
return 0;
}