BZOJ 3732: Network

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;
}
posted @ 2020-02-18 17:43  Mrzdtz220  阅读(92)  评论(0)    收藏  举报