Luogu P1967 货车运输

​ 这是一道$Kruskal$重构树的板子题,因为$Kruskal$重构树满足两节点的在原树上路径上边最大/小值为这两个点在重构树上的$LCA$的点权


#include <cstdio>
#include <algorithm>
using std::swap;
using std::sort;
typedef long long ll;

template <typename T>
inline void read (T &x) {
    x = 0; char ch = getchar();
    while (ch < '0' || ch > '9') ch = getchar();
    while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar();
}

const int N = 1e5 + 10, M = 5e4 + 10, LogN = 20;
int n, m, Q, x, y, tot, lim, fa[N << 1], poi[N];
int e_num, from[N << 1], to[N << 1], nxt[N << 1];//Edges
int dep[N], f[LogN][N << 1];//LCA
struct Edge {
    int u, v, w;
    inline bool operator < (const Edge &a) const { return w > a.w; }
} e[N << 1];

inline int find (int x) { return x == fa[x] ? x : fa[x] = find(fa[x]); }
inline void addEdge (int u, int v) {
    to[++e_num] = v, nxt[e_num] = from[u], from[u] = e_num;
}

inline void Kruskal () {
    sort(&e[1], &e[m + 1]);
    for (int i = 1, cnt = 0; i <= m && cnt < n; ++i) {
		int u = find(e[i].u), v = find(e[i].v);
		if (u == v) continue;
		poi[++tot] = e[i].w, fa[u] = fa[v] = tot;
		addEdge(tot, u), addEdge(tot, v);
    }
}

void dfs (int u) {
    for (int i = from[u]; i; i = nxt[i]) {
		int v = to[i]; dep[v] = dep[u] + 1;
		f[0][v] = u, dfs(v);
    }
}

inline int LCA (int x, int y) {
    if (dep[x] < dep[y]) swap(x, y);
    int delta = dep[x] - dep[y];
    for (int i = 0; i < LogN; ++i)
		if ((1 << i) & delta)
	    	x = f[i][x];
    if (x == y) return poi[x];
    for (int i = LogN - 1; i >= 0; --i)
		if (f[i][x] != f[i][y])
	    	x = f[i][x], y = f[i][y];
    return poi[f[0][x]];
}

int main () {
    read(n), read(m), tot = n, lim = n << 1;
    for (int i = 1; i <= lim; ++i) fa[i] = i;
    for (int i = 1; i <= m; ++i)
		read(e[i].u), read(e[i].v), read(e[i].w);
    Kruskal(), read(Q);
    for (int i = tot; i >= 1; --i)
		if (!dep[i]) dep[i] = 1, dfs(i);
    for (int i = 1; i < LogN; ++i)
		for (int j = 1; j <= tot; ++j)
		    f[i][j] = f[i - 1][f[i - 1][j]];
    while (Q--) {
		read(x), read(y);
		int fx = find(x), fy = find(y);
		if (fx != fy) puts("-1");
		else printf("%d
", LCA(x, y));
    }
    return 0;
}
原文地址:https://www.cnblogs.com/water-mi/p/9794390.html