P1967 貨車運輸
AC代碼:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cmath>
using namespace std;
const int N = 10005, M = 50005, K = 15;
int head[N], ver[N << 1], edge[N << 1], ne[N << 1];
int depth[N], fa[N][K], w[N][K], p[N];
bool visited[N];
int n, m, idx;
struct Edge{
int x, y, z;
bool operator<(const Edge& others)const{
return z > others.z;
}
}e[M];
void add(int x, int y, int z){
ver[idx] = y, edge[idx] = z, ne[idx] = head[x], head[x] = idx ++;
}
int Find(int x){
return x == p[x]? x: p[x] = Find(p[x]);
}
void bfs(int root){
queue<int>Q;
Q.push(root);
depth[root] = 1;
visited[root] = true;
while(!Q.empty()){
int x = Q.front();
Q.pop();
for(int i = head[x]; i != -1; i = ne[i]){
int y = ver[i], z = edge[i];
if(visited[y]) continue;
visited[y] = true;
depth[y] = depth[x] + 1;
Q.push(y);
fa[y][0] = x;
w[y][0] = z;
for(int k = 1; k < K; k ++){
fa[y][k] = fa[fa[y][k - 1]][k - 1];
w[y][k] = min(w[y][k - 1], w[fa[y][k - 1]][k - 1]);
}
}
}
}
int lca(int x, int y){
if(Find(x) != Find(y)) return -1;
int ans = 0x3f3f3f3f;
if(depth[x] > depth[y]) swap(x, y);
while(depth[y] > depth[x]){
ans = min(ans, w[y][int(log(depth[y] - depth[x])/log(2))]);
y = fa[y][int(log(depth[y] - depth[x])/log(2))];
}
if(x == y) return ans;
for(int k = log(depth[x])/log(2); k >= 0; k --){
if(fa[x][k] != fa[y][k]){
ans = min(ans, min(w[x][k], w[y][k]));
x = fa[x][k], y = fa[y][k];
}
}
return min(ans, min(w[x][0], w[y][0]));
}
int main(){
scanf("%d%d", &n, &m);
for(int i = 0; i < m; i ++){
scanf("%d%d%d", &e[i].x, &e[i].y, &e[i].z);
}
sort(e, e + m);
memset(head, -1, sizeof(head));
for(int i = 0; i < N; i ++) p[i] = i;
for(int i = 0; i < m; i ++){
int x = e[i].x, y = e[i].y, z = e[i].z;
int root_x = Find(x), root_y = Find(y);
if(root_x != root_y){
p[root_x] = root_y;
add(x, y, z), add(y, x, z);
}
}
for(int i = 1; i <= n; i ++){
if(!visited[i]) bfs(i);
}
int query, x, y;
scanf("%d", &query);
while(query --){
scanf("%d%d", &x, &y);
printf("%d\n", lca(x, y));
}
return 0;
}