Sub#0 前半部分WA后半部分TLE,思路是建出最大生成树的重构树,然后询问两点答案就是这两点的LCA。
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 2e4 + 5, M = 5e4 + 5;
int n, m, q, tot, fa[N][30], dep[N], d;
bool vis[N];
vector <int> T[N];
struct Ed{
int u, v, w;
}ed[M];
bool cmp(Ed x, Ed y) {
return x.w > y.w;
}
struct DSU{
int fa[N], a[N]; //a存的是新加的节点的点权
void init() {
for (int i = 1; i <= n * 2; ++i) fa[i] = i;
return ;
}
int getroot(int x) {
if(fa[x] == x) return x;
return fa[x] = getroot(fa[x]);
}
void merge(int x, int y, int w) {
// x = getroot(x), y = getroot(y);
fa[x] = fa[y] = ++n, a[n] = w;
T[n].push_back(x), T[n].push_back(y);
return ;
}
}D;
void Kruskal() {
D.init();
sort(ed + 1, ed + m + 1, cmp);
int cnt = 0;
for (int i = 1; i <= m; ++i) {
if(cnt == n - 1) break;
int u = D.getroot(ed[i].u), v = D.getroot(ed[i].v);
if(u == v) continue;
cnt++;
D.merge(u, v, ed[i].w);
T[ed[i].u].push_back(ed[i].v), T[ed[i].v].push_back(ed[i].u);
}
d = log2(n);
return ;
}
void dfs(int u, int ff) {
vis[u] = 1, fa[u][0] = ff, dep[u] = dep[ff] + 1;
for (int i = 0; i < T[u].size(); ++i) {
int v = T[u][i];
if(v == ff) continue;
dfs(v, u);
}
return ;
}
int LCA(int x, int y) {
if(x == y) return x;
if(dep[x] < dep[y]) swap(x, y);
for (int i = d; i >= 0; --i) {
if(dep[fa[x][i]] > dep[y]) x = fa[x][i];
}
if(x == y) return x;
for (int i = d; i >= 0; --i) {
if(fa[x][i] != fa[y][i]) x = fa[x][i], y = fa[y][i];
}
// if(x == y) return x;
return fa[x][0];
}
int main() {
scanf("%d %d", &n, &m);
tot = n;
for (int i = 1; i <= m; ++i) {
scanf("%d %d %d", &ed[i].u, &ed[i].v, &ed[i].w);
}
Kruskal();
for (int i = n; i > tot; --i) {
if(!vis[i]) dfs(i, i);
}
for (int i = 1; i <= d; ++i) {
for (int j = 1; j <= n; ++j) {
fa[j][i] = fa[fa[j][i - 1]][i - 1];
}
}
scanf("%d", &q);
for (int i = 1; i <= q; ++i) {
int x, y; scanf("%d %d", &x, &y);
if(D.getroot(x) != D.getroot(y)) puts("-1");
else printf("%d\n", D.a[LCA(x, y)]);
}
return 0;
}