题目原址在下面:
题目大意: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; }