• 【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
    ", LCA(a, b));
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    类和对象系列教材 (一)- 什么是Java中的引用?
    类和对象系列教材 (一)- 什么是Java中的引用?
    数组系列教材 (七)- java.util.Arrays类常用方法
    数组系列教材 (七)- java.util.Arrays类常用方法
    数组系列教材 (七)- java.util.Arrays类常用方法
    数组系列教材 (六)- Java 如何使用二维数组
    数组系列教材 (六)- Java 如何使用二维数组
    [LeetCode] 938. Range Sum of BST
    [LeetCode] 13. Roman to Integer
    [LeetCode] 12. Integer to Roman
  • 原文地址:https://www.cnblogs.com/GJY-JURUO/p/14880398.html
Copyright © 2020-2023  润新知