kruskal重构树
因为建出来的树有大根堆性质,而且kruskal过程是优先考虑短的边的
所以LCA处的值一定是最短的最长边
#include <bits/stdc++.h>
char buf[1 << 21], *p1 = buf, *p2 = buf;
inline char getc() {
return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++;
}
inline int read() {
int x = 0, f = 1; char ch = getc();
while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getc(); }
while (ch >= '0' && ch <= '9') { x = x * 10 + ch - 48; ch = getc(); }
return x * f;
}
const int N = 3e4 + 7;
struct Edge {
int u, v, c;
bool operator < (const Edge &p) const {
return c < p.c;
}
void in() {
u = read(), v = read(), c = read();
}
} edge[N];
int n, m, q, pa[N], fa[N][18], head[N], to[N], ne[N], cnt = 1, c[N];
int dep[N];
inline int find(int x) { return x == pa[x] ? x : pa[x] = find(pa[x]); }
inline void add(int u, int v) { to[++cnt] = v; ne[cnt] = head[u]; head[u] = cnt; }
void dfs(int u) {
for (int i = 1; (1 << i) <= dep[u]; i++)
if (fa[u][i - 1]) fa[u][i] = fa[fa[u][i - 1]][i - 1];
for (int i = head[u]; i; i = ne[i]) {
int v = to[i];
dep[v] = dep[u] + 1;
dfs(v);
}
}
int Lca(int u, int v) {
if (dep[u] < dep[v]) std::swap(u, v);
int dif = dep[u] - dep[v];
for (int i = 16; ~i; i--)
if (dif >> i & 1)
u = fa[u][i];
if (u == v) return u;
for (int i = 16; ~i; i--)
if (fa[u][i] != fa[v][i])
u = fa[u][i], v = fa[v][i];
return fa[u][0];
}
int main() {
n = read(), m = read(), q = read();
for (int i = 0; i < m; i++)
edge[i].in();
std::sort(edge, edge + m);
for (int i = 1; i <= 2 * n; i++)
pa[i] = i;
for (int i = 0; i < m; i++) {
int u = find(edge[i].u), v = find(edge[i].v);
if (u == v) continue;
int node = ++n;
add(node, u), add(node, v);
c[node] = edge[i].c;
pa[u] = pa[v] = node;
fa[u][0] = fa[v][0] = node;
}
for (int i = n; i; i--)
if (!dep[i]) dep[i] = 1, dfs(i);
for (int x, y; q--; ) {
x = read(), y = read();
printf("%d\n", c[Lca(x, y)]);
}
return 0;
}