题意: n个点,m条边,每条边有自己的限重,q个询问,询问满足火车从x到y的最大限重.
方法: kruscal最大生成树+树上倍增lca+rmq.
解析: 由于两个点间有可能有重边,而且我们要的是最大限重,所以选取前n-1条最大的边构成一棵树,在这棵树上进行操
作.求x到y的路径,则需要考虑x与y是否在一棵树上,不是则输出-1,在一棵树上,找出x与y的公共祖先的过程中采用
rmq记录最大的最小边权.
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std ;
struct node
{
int from ;
int to ;
int val ;
int next ;
};
node edge[100001] ;
node l[50001] ;
int head[10001] ;
int fa[10001][20] ;
int deep[10001] ;
int v[10001] ;
int sum[10001][20] ;
int f[10001] ;
int cnt , n , m , tot , pt;
int find(int x)
{
if(f[x] == x) return x ;
else
{
f[x] = find(f[x]) ;
return f[x] ;
}
}
void init()
{
memset(head , -1 , sizeof(head)) ;
memset(sum , 0x3f , sizeof(sum)) ;
cnt = 1 ;
for(int i = 1 ; i <= n ; i++) f[i] = i ;
}
void dfs(int now , int f , int dep)
{
v[now] = 1 ;
deep[now] = dep ;
for(int i = head[now] ; i != -1 ; i = edge[i].next)
{
int to = edge[i].to ;
if(to == f) continue ;
fa[to][0] = now ;
sum[to][0] = edge[i].val ;
dfs(to , now , dep + 1) ;
}
}
void edgeadd(int from , int to , int val)
{
edge[cnt].from = from ;
edge[cnt].to = to ;
edge[cnt].val = val ;
edge[cnt].next = head[from] ;
head[from] = cnt ++ ;
}
int cmp(node a , node b)
{
return a.val > b.val ;
}
int lca(int x , int y)
{
pt = 0x3f3f3f3f ;
int re ;
if(deep[x] < deep[y]) swap(x , y) ;
for(int i = 18 ; i >= 0 ; i--)
{
if(deep[fa[x][i]] >= deep[y]&&fa[x][i]!=0) pt = min(sum[x][i] , pt) ,x = fa[x][i] ;
}
if(x == y) return x ;
for(int i = 18 ; i >= 0 ; i--)
{
if(fa[x][i] != fa[y][i]&&fa[x][i]&&fa[y][i])
{
pt = min(sum[x][i] , pt) ;
pt = min(sum[y][i] , pt) ;
x = fa[x][i] , y = fa[y][i] ;
}
}
pt = min(pt , min(sum[x][0] , sum[y][0])) ;
return re ;
}
int main()
{
scanf("%d%d" , &n , &m) ;
init() ;
for(int i = 1 ; i <= m ; i++)
{
scanf("%d%d%d" , &l[i].from , &l[i].to , &l[i].val) ;
}
sort(l + 1 , l + m + 1 , cmp) ;
for(int i = 1 ; i <= m ; i++)
{
int x = l[i].from , y = l[i].to ;
int fx = find(x) , fy = find(y) ;
if(fx != fy)
{
tot ++ ;
f[fx] = fy ;
edgeadd(x , y , l[i].val) ;
edgeadd(y , x , l[i].val) ;
if(tot == n-1)
{
break ;
}
}
}
for(int i = 1 ; i <= n ; i++)
{
if(!v[i]) dfs(i , 0 , 1) ;
}
for(int j = 0 ; (1 << j) <= n ; j++)
{
for(int i = 1 ; i <= n ; i++)
{
if(fa[fa[i][j-1]][j-1] != 0)
{
fa[i][j] = fa[fa[i][j-1]][j-1] ;
sum[i][j] = min(sum[i][j-1] , sum[fa[i][j-1]][j-1]) ;
}
}
}
int q ;
scanf("%d" , &q) ;
for(int i = 1 ; i <= q ; i++)
{
int x , y ;
scanf("%d%d" , &x , &y) ;
if(find(x) != find(y))
{
printf("-1\n") ;
continue ;
}
int t = lca(x , y) ;
printf("%d\n" , pt) ;
}
}