题目链接:https://nanti.jisuanke.com/t/T2015
题意:给你n个点,m条双向边,并告诉你每条边的u,v,w。再给你q次询问,每次询问查询x和y之间路径的w的最小值(让w尽可能大)。
解法:根据Kruskal算法的性质可以知道,按排序从大到小即是最大生成树,所以我们想这个题目的时候就要从性质入手,题目要求的是每条边的w的最小值尽可能最大,所以我们可以构造一个最大生成树建立新图,然后结合对于倍增数组的理解,来询问2点间的最小值。注意该题可能构造出一个森林,所以需要用并查集判是否在一个树上,如果不是的话直接输出-1即可。
AC代码:

#include<bits/stdc++.h> #pragma GCC optimize(2) #define ll long long #define rep(i,a,n) for(int i=a;i<=n;i++) #define per(i,n,a) for(int i=n;i>=a;i--) #define endl ' ' #define eps 0.000000001 #define pb push_back #define mem(a,b) memset(a,b,sizeof(a)) #define IO ios::sync_with_stdio(false);cin.tie(0); using namespace std; const int INF=0x3f3f3f3f; const ll inf=0x3f3f3f3f3f3f3f3f; const int mod=1e9+7; const int maxn=1e5+5; int n,m,f[maxn]; int tot,head[maxn]; struct E{ int to,next,w; }edge[maxn<<1]; void add(int u,int v,int w){ edge[tot].to=v; edge[tot].w=w; edge[tot].next=head[u]; head[u]=tot++; } struct node{ int u,v,w; }eg[maxn<<2]; bool cmp(node a,node b){ return a.w>b.w; } inline int find(int x){ while(x!=f[x]) x=f[x]=f[f[x]]; return x; } inline void kruskal(){ int eu,ev,cnt=0; sort(eg+1,eg+m+1,cmp); for(int i=1;i<=m;i++){ eu=find(eg[i].u),ev=find(eg[i].v); if(eu==ev) continue; int u=eg[i].u,v=eg[i].v,w=eg[i].w; add(u,v,w);add(v,u,w); f[ev]=eu; if(++cnt==n-1) break; } } int fa[maxn][40],depth[maxn]; int rmq[maxn][40]; bool vis[maxn]; void dfs(int u,int step){ depth[u]=step;vis[u]=1; for(int i=head[u];i!=-1;i=edge[i].next){ int v=edge[i].to,w=edge[i].w; if(vis[v]) continue; fa[v][0]=u; rmq[v][0]=w; dfs(v,step+1); } } void bz(){ for(ll j=1;j<=19;j++){ for(ll i=1;i<=n;i++){ fa[i][j]=fa[fa[i][j-1]][j-1]; rmq[i][j]=min(rmq[i][j-1],rmq[fa[i][j-1]][j-1]); } } } ll LCA(ll u,ll v){ if(depth[u]<depth[v]) swap(u,v); ll dc=depth[u]-depth[v]; for(ll i=0;i<30;i++){ if((1<<i)&dc){ u=fa[u][i]; } } if(u==v) return u; for(ll i=29;i>=0;i--){ if(fa[u][i]!=fa[v][i]){ u=fa[u][i]; v=fa[v][i]; } } u=fa[u][0]; return u; } int search(int u,int v){ if(depth[u]<depth[v]) swap(u,v); int dc=depth[u]-depth[v]; int ans=INF; for(int i=0;i<30;i++){ if((1<<i)&dc){ ans=min(ans,rmq[u][i]); u=fa[u][i]; } } if(u==v) return ans; } int main(){ scanf("%d%d",&n,&m); mem(rmq,INF); mem(head,-1); rep(i,1,n) f[i]=i; rep(i,1,m){ int u,v,w; scanf("%d%d%d",&eg[i].u,&eg[i].v,&eg[i].w); } kruskal(); dfs(1,1); bz(); int t;scanf("%d",&t); while(t--){ int l,r;cin>>l>>r; if(find(l)!=find(r)){ printf("-1 "); continue; } int lca=LCA(l,r); int res=min(search(l,lca),search(r,lca)); printf("%d ",res); } } /* 4 3 1 2 4 2 3 3 3 1 1 3 1 3 1 4 1 3 */