#include <bits/stdc++.h>//头文件
#define ll long long
#define ull unsigned long long//个人习惯
using namespace std;
const int maxn=500010;//方便一点
const int maxm=300000;
struct edg{//x,y间权值l
int x,y,l;
}A[maxn];//原图
struct EDG{
int spot1,spot2,len;
}B[maxn];//建图
int n,m;//城市与道路
int father[maxn];//爸爸(下面那个kruskal并查集里的)
int fa[maxn][30],we[maxn][30],dp[maxn];//爸爸,最大载重(边权)和树深
int head[maxn];
int ans=0x7fffffff;//答案
//lca里要求最小值,所以设大点,0x3f,0x3f3f3f3f,0x3fffffff容易爆
bool vis[maxn];//标记一下,非0即1
int find(int x){//路径压缩
if(father[x]==x) return x;
return father[x]=find(father[x]);
}
bool cmp(edg a,edg b){//cmp排序
return a.l>b.l;
}
int cnt;
void add(int x,int y,int l){//对应原图
//最大生成树弄出来的图
B[++cnt].spot1=y;//书上说这叫链式前向星储存
B[cnt].len=l;
B[cnt].spot2=head[x];
head[x]=cnt;
return;
}
void Kruskal_max(){//求最大生成树
sort(A+1,A+m+1,cmp);//最大生成树就和最小排序反一下
for(int i=1;i<=n;i++) father[i]=i;//并查集初始化
for(int i=1;i<=m;i++){//emm网上的kruskal最大都是1~m或0~m-1耶,为什么和最小生成树不一样呢?
int ga=find(A[i].x),gb=find(A[i].y);
if(ga!=gb){
father[ga]=gb;//请叫我老师板子的搬运工
add(A[i].x,A[i].y,A[i].l);//开始搬运,原图->建的图
add(A[i].y,A[i].x,A[i].l);//无向,所以搬两次
}
}
return;//搬完了,拜拜
}
void dfs(int bj){//标记的意思,~~不是拼音党~~,想不到其他变量名了
vis[bj]=1;//标记
for(int i=head[bj];i;i=B[i].spot2){//i从邻接表的表头开始每次更新为spot2遍历下一个邻接点
int st;//起点
st=B[i].spot1;
if(vis[st]) continue;//没来过
fa[st][0]=bj;//存父节点
we[st][0]=B[i].len;//存到父亲那的权值
dp[st]=dp[bj]+1;//计算树深
//有点蒙
dfs(st);//一轮结束
}
return;//快跑
}
void swapp(int &a,int &b){//自制swap函数
int c;
c=a;a=b;b=c;//换ab
return;
}
int LCA_bz(int x,int y){//倍增lca,开始模书上板子
if(find(x)!=find(y)) return -114514;//不连通的标记
if(dp[y]>dp[x]) swapp(x,y);//让x置于最底层,使x深度值更大
for(int i=20;i>=0;i--){
if(dp[fa[x][i]]>=dp[y]){
ans=min(ans,we[x][i]);//更新ans(最小边权)
x=fa[x][i];//修改;
}
}
if(x==y) return ans;//相等了,答案
for(int i=20;i>=0;i--){
if(fa[x][i]!=fa[y][i]){//爸爸不等就继续
ans=min(min(we[x][i],we[y][i]),ans);//接着更新ans
x=fa[x][i];y=fa[y][i];//改x,y的位置
}
}
ans=min(min(we[x][0],we[y][0]),ans);//梅开三度的更新
//这时we[x][0],we[y][0]就是公共祖先
return ans;//答案,你是我的神
}//板子改完哩
int main(){
cin>>n>>m;//点(城市)和边(道路)
for(int i=1;i<=m;i++){//m次输入
cin>>A[i].x>>A[i].y>>A[i].l;//存题目的图
}
Kruskal_max();
for(int i=1;i<=n;i++){//dfs环节
if(vis[i]==0){
dp[i]=1;//深度
dfs(i);
fa[i][0]=i;
we[i][0]=0x7fffffff;//要求最小的载重,初始值得大
}
}
for(int i=1;i<=20;i++){//lca初始化,书上
for(int j=1;j<=n;j++){
fa[j][i]=fa[fa[j][i-1]][i-1];
we[j][i]=min(we[j][i-1],we[fa[j][i-1]][i-1]);
}
}
int p;
cin>>p;
for(int i=1;i<=p;i++){//p次询问
int x,y;
cin>>x>>y;
int as=LCA_bz(y,x);
ans=0x7fffffff;
if(as==-114514) cout<<-1<<endl;//lca返回值
else cout<<as<<endl;
}
return 0;//不华丽的结束
}
这段代码Subtask0第一个测试点输出:
6991
28236
6991
6991
但是我下载的数据里正确输出是:
6991
28368
6991
6991
