• 题解【洛谷P1967】[NOIP2013]货车运输


    题面

    题解

    注意到有一些限重很低的边不会被走到。

    于是考虑建一棵最大生成树,在生成树上寻找答案。

    (f[i][j])表示(i)(2^j)级祖先,(w[i][j])表示(i)(2^j)级祖先的最大载重。

    那么我们在倍增寻找( ext{LCA})时更新答案即可。

    代码

    #include <bits/stdc++.h>
    #define itn int
    #define gI gi
    
    using namespace std;
    
    inline int gi()
    {
    	int f = 1, x = 0; char c = getchar();
    	while (c < '0' || c > '9') {if (c == '-') f = -1; c = getchar();}
    	while (c >= '0' && c <= '9') x = x * 10 + (c ^ 48), c = getchar();
    	return f * x;
    }
    
    const int maxn = 100003;
    
    int q, n, m, tot, head[maxn], ver[maxn], edge[maxn], nxt[maxn], fa[maxn][23];
    int f[maxn], w[maxn][23], vis[maxn], dep[maxn];
    struct Node
    {
    	int u, v, w;
    } e[maxn];
    
    inline bool cmp(Node x, Node y) {return x.w > y.w;}
    
    int getf(int u)
    {
    	if (f[u] == u) return u;
    	return f[u] = getf(f[u]);
    }
    
    inline void add(int u, int v, int w)
    {
    	ver[++tot] = v, nxt[tot] = head[u], edge[tot] = w, head[u] = tot;
    }
    
    inline void get_MST()
    {
    	for (int i = 1; i <= n; i+=1) f[i] = i;
    	for (int i = 1; i <= m; i+=1)
    	{
    		int U = getf(e[i].u), V = getf(e[i].v);
    		if (U != V)
    		{
    			f[U] = V;
    			add(e[i].u, e[i].v, e[i].w);
    			add(e[i].v, e[i].u, e[i].w);
    		}
    	}
    }
    
    void dfs(int u)
    {
    	vis[u] = 1;
    	for (int i = head[u]; i; i = nxt[i])
    	{
    		int v = ver[i], ww = edge[i];
    		if (vis[v]) continue;
    		dep[v] = dep[u] + 1;
    		fa[v][0] = u;
    		w[v][0] = ww;
    		dfs(v);
    	}
    }
    
    inline int getans(int u, int v)
    {
    	if (dep[u] > dep[v]) swap(u, v);
    	int uu = 0x3f3f3f3f;
    	for (int i = 20; i >= 0; i-=1)
    	{
    		if (dep[fa[v][i]] >= dep[u]) uu = min(uu, w[v][i]),  v = fa[v][i];
    	}
    	if (u == v) return uu;
    	for (int i = 20; i >= 0; i-=1)
    	{
    		if (fa[u][i] != fa[v][i])
    		{
    			uu = min(uu, min(w[u][i], w[v][i]));
    			u = fa[u][i], v = fa[v][i];
    		}
    	}
    	uu = min(uu, min(w[u][0], w[v][0]));
    	return uu;
    }
    
    int main()
    {
    	//freopen(".in", "r", stdin);
    	//freopen(".out", "w", stdout);
    	n = gi(), m = gi();
    	for (int i = 1; i <= m; i+=1)
    	{
    		int u = gi(), v = gi(), w = gi();
    		e[i].u = u, e[i].v = v, e[i].w = w;
    	}
    	sort(e + 1, e + 1 + m, cmp);
    	get_MST();
    	for (int i = 1; i <= n; i+=1)
    	{
    		if (!vis[i])
    		{
    			dep[i] = 1;
    			dfs(i);
    			fa[i][0] = i;
    			w[i][0] = 0x3f3f3f3f;
    		}
    	}
    	for (int i = 1; i <= 20; i+=1)
    		for (int j = 1; j <= n; j+=1)
    			fa[j][i] = fa[fa[j][i - 1]][i - 1],
    				w[j][i] = min(w[j][i - 1], w[fa[j][i - 1]][i - 1]);
    	q = gi();
    	while (q--)
    	{
    		int u = gi(), v = gi();
    		if (getf(u) != getf(v)) {puts("-1"); continue;}
    		printf("%d
    ", getans(u, v));
    	}
    	return 0;
    }
    
  • 相关阅读:
    【Linux】5.5 Shell运算符
    【Linux】5.4 Shell数组
    【Linux】5.3 Shell字符串
    【Linux】5.2 Shell变量
    【Linux】5.1 Shell简介
    【Linux】3.11 包管理工具(RPM和YUM)
    【Linux】3.10 进程管理(重点)
    【Linux】3.9 网络配置
    【Linux】3.8 Linux磁盘分区、挂载
    【Linux】3.7 定时任务调度
  • 原文地址:https://www.cnblogs.com/xsl19/p/11830579.html
Copyright © 2020-2023  润新知