[题解] uva 11354 Bond(kruskal最小生成树+倍增LCA)
- 传送门 -
https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2339
const int N = 5e4 + 5;
const int M = 1e5 + 5;
const int inf = 0x7fffffff;
struct edge {
int x, y, v;
}W[M];
int D[N], ANC[N][18], MA[N][18];
int HD[N], NXT[M], TO[M], V[M];
int F[N];
int n, m, q, cnt, sz, tot;
bool cmp (edge a, edge b) { return a.v < b.v; }
void init() {
sz = cnt = tot = 0;
memset(ANC, 0, sizeof (ANC));
memset(MA, 0, sizeof (MA));
memset(HD, 0, sizeof (HD));
memset(D, 0, sizeof (D));
for (int i = 1; i <= n; ++i)
F[i] = i;
}
void add(int x, int y, int v) {
TO[++tot] = y; NXT[tot] = HD[x]; HD[x] = tot; V[tot] = v;
TO[++tot] = x; NXT[tot] = HD[y]; HD[y] = tot; V[tot] = v;
}
int find(int x) { return x == F[x] ? x : F[x] = find(F[x]); }
void kruskal() {
for (int i = 0; i < m; ++i) {
int fx = find(W[i].x), fy = find(W[i].y);
if (fx == fy) continue;
cnt ++;
F[fx] = fy;
add(W[i].x, W[i].y, W[i].v);
if (cnt == n - 1) break;
}
}
void dfs(int x) {
for (int i = 1; i <= 16; ++i) {
ANC[x][i] = ANC[ANC[x][i-1]][i-1];
MA[x][i] = max(MA[x][i-1], MA[ANC[x][i-1]][i-1]);
}
for (int i = HD[x]; i; i = NXT[i]) {
int v = TO[i];
if (v != ANC[x][0]) {
D[v] = D[x] + 1;
ANC[v][0] = x;
MA[v][0] = V[i];
dfs(v);
}
}
}
void lca(int x, int y) {
int ans = -inf;
if (D[x] < D[y]) swap(x, y);
for (int i = 16; i >= 0; --i)
if (D[ANC[x][i]] >= D[y]) {
ans = max(ans, MA[x][i]);
x = ANC[x][i];
}
if (x != y) {
for (int i = 16; i >= 0; --i)
if (ANC[x][i] != ANC[y][i]) {
ans = max(ans, MA[x][i]);
ans = max(ans, MA[y][i]);
x = ANC[x][i];
y = ANC[y][i];
}
ans = max(ans, MA[x][0]);
ans = max(ans, MA[y][0]);
}
printf("%d\n", ans);
}
int main() {
int cas = 0;
while (scanf("%d%d", &n, &m) != EOF) {
if (cas) printf("\n");
else cas ++;
init();
for (int i = 0; i < m; ++i)
scanf("%d%d%d", &W[i].x, &W[i].y, &W[i].v);
sort(W, W + m, cmp);
kruskal();
for (int i = 1; i <= n; ++i)
if (!D[i]) dfs(i);
scanf("%d", &q);
for (int i = 1, x, y; i <= q; ++i) {
scanf("%d%d", &x, &y);
lca(x, y);
}
}
return 0;
}