题意:给出一张n个点m条边的无向图, 每条边有一个危险度,有q个询问, 每次给出两个点s、t,找一条路, 使得路径上的最大危险度最小
按秩合并并查集
不能路径压缩 否则就破坏了其树形结构
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> using namespace std; //input by bxd #define rep(i,a,b) for(int i=(a);i<=(b);i++) #define repp(i,a,b) for(int i=(a);i>=(b);--i) #define ll long long #define see(x) (cerr<<(#x)<<'='<<(x)<<endl) #define pb push_back #define inf 0x3f3f3f3f #define CLR(A,v) memset(A,v,sizeof A) typedef pair<int,int>pii; ////////////////////////////////// const int N=1e6+10; int f[N],x,y,q,n,m,siz[N],w[N]; struct Edge { int u,v,w; }edge[N]; int find1(int x) { return f[x]==x?x:find1(f[x]); } void kruscal() { sort(edge+1,edge+1+m,[](Edge a,Edge b){return a.w<b.w;}); int cnt=0; rep(i,1,n)f[i]=i,siz[i]=1; CLR(w,0); rep(i,1,m) { int x=find1(edge[i].u),y=find1(edge[i].v); if(x==y)continue; if(siz[x]<siz[y]) { f[x]=y; siz[y]=max(siz[y],siz[x]+1); w[x]=edge[i].w; } else { f[y]=x; siz[x]=max(siz[x],siz[y]+1); w[y]=edge[i].w; } cnt++; if(cnt==n-1)break; } } int c[N]; int query(int x,int y) { rep(i,1,n)c[i]=-1; int ans=0,temp=0; while(1) { c[x]=temp; if(f[x]==x)break; temp=max(temp,w[x]); x=f[x]; } while(1) { if(c[y]>=0){ans=max(ans,c[y]);break;}//lca相同时就退出 if(f[y]==y)break; ans=max(ans,w[y]); y=f[y]; } return ans; } int main() { int ok=0; while(scanf("%d%d",&n,&m)==2) { if(ok)printf(" "); ok=1; rep(i,1,m) scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].w); kruscal(); scanf("%d",&q); while(q--) { scanf("%d%d",&x,&y); printf("%d ",query(x,y)); } } return 0; }