P1967 我用的 Kruskal 重构树,但是注释处如果按照题目数据范围来写,第一个 Subtask 最后几个点还会 RE,这样写才能过,为什么
#include <iostream>
#include <cstdio>
#include <algorithm>
const int N = 1e6 + 7; //here
const int M = 5e6 + 7;
const int J = 30;
class edge {
public:
int tail;
int head;
int weight;
friend bool operator < (edge x, edge y) {
return x.weight < y.weight;
}
friend bool operator > (edge x, edge y) {
return x.weight > y.weight;
}
};
edge e[M];
int o;
int lch[N << 1], rch[N << 1];
int wei[N << 1];
bool vis[N << 1];
int cnt;
int fak[J][N << 1], dep[N << 1];
int logn[N << 1];
int n, m;
int q;
int fas[N << 1];
inline void add(int x, int y, int w) {
e[o++] = (edge){x, y, w};
}
int find(int x) {
return x == fas[x] ? x : (fas[x] = find(fas[x]));
std::cout << "de\n";
}
void kruskal() {
std::sort(e, e + m, std::greater <edge>());
for(int i = 0; i < m; i++) {
int u = e[i].tail, v = e[i].head;
u = find(u), v = find(v);
if(u != v) {
cnt++;
fas[v] = cnt;
fas[u] = cnt;
lch[cnt] = u;
rch[cnt] = v;
wei[cnt] = e[i].weight;
}
}
}
void init(int u, int f) {
fak[0][u] = f;
dep[u] = dep[f] + 1;
for(int i = 1; i <= logn[dep[u]]; i++)
fak[i][u] = fak[i - 1][fak[i - 1][u]];
if(lch[u] != 0) init(lch[u], u);
if(rch[u] != 0) init(rch[u], u);
}
int cal(int x, int y) {
if(find(x) != find(y)) return -1;
int rt = find(x);
if(!vis[rt]) init(rt, 0), vis[rt] = true;
if(dep[x] > dep[y]) std::swap(x, y);
for(int i = logn[dep[y]]; i >= 0; i--)
if(dep[fak[i][y]] >= dep[x])
y = fak[i][y];
if(x == y) return wei[x];
for(int i = logn[dep[y]]; i >= 0; i--)
if(fak[i][x] != fak[i][y])
x = fak[i][x], y = fak[i][y];
return wei[x == y ? x : fak[0][x]];
}
int main() {
std::freopen("test.in", "r", stdin);
std::cin >> n >> m;
cnt = n;
logn[1] = 0;
for(int i = 1; i <= n; i++)
logn[i] = logn[i / 2] + 1;
for(int i = 1; i <= 2 * n + 1; i++)
fas[i] = i;
int x, y, z;
for(int i = 0; i < m; i++) {
std::cin >> x >> y >> z;
add(x, y, z);
}
kruskal();
std::cin >> q;
for(int i = 0; i < q; i++) {
std::cin >> x >> y;
std::cout << cal(x, y) << '\n';
}
return 0;
}