【YBTOJ】【Luogu P1967】[NOIP2013 提高组] 货车运输

链接:

洛谷

题目大意:

给定一个图,每次问两点,求两点间最小值最大是多少。

正文:

两点间不只有一条路径,我们要求“最大”,实际上是将它化为只有一条路径,即最大生成树。

接着就是树剖板子题,但也可以用 LCA 做。

代码:

const int N = 1e4 + 10;

inline ll Read()
{
	ll x = 0, f = 1;
	char c = getchar();
	while (c != '-' && (c < '0' || c > '9')) c = getchar();
	if (c == '-') f = -f, c = getchar();
	while (c >= '0' && c <= '9') x = (x << 3) + (x << 1) + c - '0', c = getchar();
	return x * f;
}

int n, m, Log;

int head[N], tot;
struct node
{
	int from, to, val, nxt;
	bool operator < (const node &a) const
	{
		return val > a.val;
	}
}e[10 * N], inp[10 * N];

void add(int u, int v, int w)
{
	e[++tot] = (node){u, v, w, head[u]}, head[u] = tot; 
}

int fa[N];
int Find(int k) {return k == fa[k]? k: fa[k] = Find(fa[k]);} 

int dep[N], f[N][27], g[N][27];
void dfs(int u, int d)
{
	dep[u] = d;
	for (int v, i = head[u]; i; i = e[i].nxt)
	{
		if (dep[v = e[i].to]) continue;
		g[v][0] = e[i].val, f[v][0] = u;
		for (int j = 1; j <= Log; j++)
			f[v][j] = f[f[v][j - 1]][j - 1],
			g[v][j] = min(g[v][j - 1], g[f[v][j - 1]][j - 1]);
		dfs(v, d + 1);
	}
}

int LCA(int u, int v)
{
	if (Find(u) != Find(v)) return -1;
	if (dep[u] > dep[v]) u ^= v ^= u ^= v;
	int ans = 707406378;
	for (int j = Log; ~j; j--)
		if (dep[f[v][j]] >= dep[u])
			ans = min(ans, g[v][j]),
			v = f[v][j];
	if (u == v) return ans;
	for (int j = Log; ~j; j--)
		if (f[u][j] != f[v][j])
			ans = min(ans, min(g[v][j], g[u][j])),
			u = f[u][j], v = f[v][j];
	return min(ans, min(g[u][0], g[v][0]));
}

int main()
{
	memset (g, 127 / 3, sizeof g);
	n = Read(), m = Read();
	Log = log2(n) + 1; 
	for (int i = 1; i <= m; i++)
	{
		int u = Read(), v = Read(), w = Read();
		inp[i] = (node){u, v, w, 0}; 
	}
	sort (inp + 1, inp + 1 + m);
	for (int i = 1; i <= n; i++) fa[i] = i;
	for (int i = 1; i <= m; i++)
	{
		int u = inp[i].from, v = inp[i].to, w = inp[i].val,
		    U = Find(u), V = Find(v);
		if (U == V) continue;
		fa[U] = V;
		add(u, v, w), add(v, u, w);
	}
	for (int i = 1; i <= n; i++) 
		if (!dep[i]) dfs(i, 1);
	for (int t = Read(); t--; )
	{
		int a = Read(), b = Read();
		printf ("%d\n", LCA(a, b));
	}
	return 0;
}

posted @ 2021-06-13 15:41  Jayun  阅读(32)  评论(0编辑  收藏  举报