题面
kruskal重构树:kruskal的过程中每通过一条边合并两个集合 就新建一个结点作为代表这两个集合的结点的父亲,点权为该边边权
叶子结点都是原图中的点==
那么不难发现父节点点权都大于子节点
刚好使询问的两点所在集合合并的边的边权就是所求 即重构树上lca的点权
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
const int maxn = 30007;
#define ll long long;
int n, m, q, res, c;
struct edge{
int u, v, w;
bool operator < (const edge &rhs) const {
return w < rhs.w;
}
}e[maxn << 1];
vector<int> adj[maxn << 1];
int dep[maxn << 1], top[maxn << 1], son[maxn << 1], dfl[maxn << 1], tot, siz[maxn << 1], w[maxn << 1], f[maxn << 1];
int fa[maxn << 1];
int get(int x){return fa[x] == x ? x : fa[x] = get(fa[x]);}
int read(){
int s = 0; char c = getchar();
while (c > '9' || c < '0') c = getchar();
while (c >= '0' && c <= '9') {
s = s * 10 + c - '0';
c = getchar();
}
return s;
}
void dfs1(int u) {
siz[u] = 1;
for (int i = 0; i < adj[u].size(); i++) {
int v = adj[u][i];
dep[v] = dep[u] + 1;
f[v] = u;
dfs1(v);
siz[u] += siz[v];
if (siz[v] > siz[son[u]]) son[u] = v;
}
}
void dfs2(int u, int t){
dfl[u] = ++tot; top[u] = t;
if (son[u]) {
dfs2(son[u], t);
for (int i = 0; i < adj[u].size(); i++) {
int v = adj[u][i];
if (v != son[u] && v != f[u]) dfs2(v, v);
}
}
}
int lca(int u, int v) {
while (top[u] ^ top[v]) {
if (dep[top[u]] < dep[top[v]]) swap(u, v);
u = f[top[u]];
}
return dep[u] < dep[v] ? u : v;
}
int main(){
n = read(), m = read(), q = read();
for (int i = 1; i <= m; i++) e[i].u = read(), e[i].v = read(), e[i].w = read();
sort(e + 1, e + m + 1);
for (int i = 1; i <= n << 1; i++) fa[i] = i;
c = n;
for (int i = 1, r = n - 1; i <= m && r > 0; i++) {
int u = get(e[i].u), v = get(e[i].v);
if (u ^ v) {
w[++c] = e[i].w;
fa[u] = fa[v] = c;
adj[c].push_back(u); adj[c].push_back(v);
r--;
}
}
dfs1(c); dfs2(c, c);
for (int i = 1; i <= q; i++) {
printf("%d\n", w[lca(read(), read())]);
}
return 0;
}