LightOJ - 1162 Min Max Roads

题解:在线倍增LCA和模拟ST表

让我们求从\(u->v\)最短路径上的边权最大值和边权最小值,那么我们可以利用倍增思想,类似其\(fa[u][i]\)数组代表从\(u\)往上跳\(2^i\)步的点这一思想,我们可以建立两个二维数组\(dmax[u][i],dmin[u][i]\),代表从\(u\)往上跳\(2^i\)步到达的点和\(u\)之间路径的最大权值和最小权值,同时我们可以知道dmax和dmin的初始状态:\(dmax[u][0]=dmin[u][0]=w_i\),最后类似\(fa[u][i] = fa[fa[u[i-1]]][i-1]\)我们列出状态方程:\(dmax[u][i]=max(dmax[u][i-1],dmax[fa[u][i-1]][i-1])\),\(dmin[u][i]=min(dmin[u][i-1],dmin[fa[u][i-1]][i-1])\),

这就类似ST表的思想,一个区间的最大值是可重复的贡献,所以我们各取区间的一半分别取\(max/min\),所以这个方程就代表:从\(u\)往上跳\(2^i\)步到达的点和\(u\)之间路径的最大权值和最小权值,\([u,2^i] = max/min([u,2^{i-1}],[u+2^{i-1},u+2^i])\)

#include <bits/stdc++.h>
#define Zeoy std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0)
#define all(x) (x).begin(), (x).end()
#define endl '\n'
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-9;
const int N = 1e5 + 10;
int n, m;
int fa[N][22], dmax[N][22], dmin[N][22];
int du[N], dep[N];
vector<pii> g[N];
void init()
{
memset(fa, 0, sizeof fa);
memset(dmax, 0, sizeof dmax);
memset(dmin, 0, sizeof dmin);
for (int i = 1; i <= n; ++i)
du[i] = 0, dep[i] = 0, g[i].clear();
}
void dfs(int u, int par, int w)
{
dep[u] = dep[par] + 1;
fa[u][0] = par;
dmax[u][0] = w;
dmin[u][0] = w;
for (int i = 1; i <= 20; ++i)
{
fa[u][i] = fa[fa[u][i - 1]][i - 1];
dmax[u][i] = max(dmax[u][i - 1], dmax[fa[u][i - 1]][i - 1]);
dmin[u][i] = min(dmin[u][i - 1], dmin[fa[u][i - 1]][i - 1]);
}
for (auto &[v, W] : g[u])
{
if (v == par)
continue;
dfs(v, u, W);
}
}
void lca(int u, int v)
{
int maxx = -inf, minn = inf;
if (dep[u] < dep[v])
swap(u, v);
for (int i = 20; i >= 0; i--)
{
if (dep[fa[u][i]] >= dep[v])
{
maxx = max(maxx, dmax[u][i]); //注意一定要先去取区间max和min,不然u就会改变
minn = min(minn, dmin[u][i]);
u = fa[u][i];
}
}
if (u == v)
{
cout << minn << " " << maxx << endl;
return;
}
for (int i = 20; i >= 0; --i)
{
if (fa[u][i] != fa[v][i])
{
maxx = max({maxx, dmax[u][i], dmax[v][i]});
minn = min({minn, dmin[u][i], dmin[v][i]});
u = fa[u][i], v = fa[v][i];
}
}
maxx = max({maxx, dmax[u][0], dmax[v][0]});
minn = min({minn, dmin[u][0], dmin[v][0]});
cout << minn << " " << maxx << endl;
}
int main(void)
{
Zeoy;
int t = 1;
cin >> t;
int tot = 1;
while (t--)
{
cin >> n;
cout << "Case " << tot++ << ":\n";
init();
for (int i = 1, u, v, w; i < n; ++i)
{
cin >> u >> v >> w;
du[v]++;
g[u].push_back({v, w});
g[v].push_back({u, w});
}
int st;
for (int i = 1; i <= n; ++i)
{
if (du[i] == 0)
{
st = i;
break;
}
}
dfs(st, 0, 0);
cin >> m;
for (int i = 1, u, v; i <= m; ++i)
{
cin >> u >> v;
lca(u, v);
}
}
return 0;
}

LightOJ - 1162 Min Max Roads的更多相关文章

  1. 在一定[min,max]区间,生成n个不重复的随机数的封装函数

    引:生成一个[min,max]区间的一个随机数,随机数生成相关问题参考→链接 var ran=parseInt(Math.random()*(max-min+1)+min); //生成一个[min,m ...

  2. LINQ to SQL Count/Sum/Min/Max/Avg Join

    public class Linq { MXSICEDataContext Db = new MXSICEDataContext(); // LINQ to SQL // Count/Sum/Min/ ...

  3. 2.10 用最少次数寻找数组中的最大值和最小值[find min max of array]

    [本文链接] http://www.cnblogs.com/hellogiser/p/find-min-max-of-array.html [题目] 对于一个由N个整数组成的数组,需要比较多少次才能把 ...

  4. LINQ Count/Sum/Min/Max/Avg

    参考:http://www.cnblogs.com/peida/archive/2008/08/11/1263384.html Count/Sum/Min/Max/Avg用于统计数据,比如统计一些数据 ...

  5. 【转载】:【C++跨平台系列】解决STL的max()与numeric_limits::max()和VC6 min/max 宏冲突问题

    http://www.cnblogs.com/cvbnm/articles/1947743.html 多年以前,Microsoft 幹了一件比 #define N 3 還要蠢的蠢事,那就是在 < ...

  6. LINQ to SQL 语句(3) 之 Count/Sum/Min/Max/Avg

    LINQ  to SQL 语句(3) 之  Count/Sum/Min/Max/Avg [1] Count/Sum 讲解 [2] Min 讲解 [3] Max 讲解 [4] Average 和 Agg ...

  7. [转]LINQ语句之Select/Distinct和Count/Sum/Min/Max/Avg

    在讲述了LINQ,顺便说了一下Where操作,这篇开始我们继续说LINQ语句,目的让大家从语句的角度了解LINQ,LINQ包括LINQ to Objects.LINQ to DataSets.LINQ ...

  8. 动态规划——min/max的单调性优化总结

    一般形式: $max\{min(ax+by+c,dF(x)+eG(y)+f)\},其中F(x)和G(y)是单调函数.$ 或 $min\{max(ax+by+c,dF(x)+eG(y)+f)\},其中F ...

  9. Hive函数:SUM,AVG,MIN,MAX

    转自:http://lxw1234.com/archives/2015/04/176.htm,Hive分析窗口函数(一) SUM,AVG,MIN,MAX 之前看到大数据田地有关于max()over(p ...

  10. 产生10个随机数5-9之间 统计一个int类型的一维数组中有多少个在[min,max]之间的数

    * 产生10个随机数5-9之间 统计一个int类型的一维数组中有多少个在[min,max]之间的数 */ import java.util.*; public class Demo{ public s ...

随机推荐

  1. Ubuntu vmware共享文件夹自动挂载

    自动挂载 修改/etc/fstab,加入如下内容 .host:/ /mnt/hgfs fuse.vmhgfs-fuse allow_other,defaults 0 0 手动挂载 修改/etc/fst ...

  2. typora永久插入图片

    https://c.runoob.com/front-end/59 首先将图片通过在线转码工具转换成base64的编码,并用以下格式嵌入即可,格式如下: ![image] (base64) 但是由于这 ...

  3. UBUNTU切换内核

    查询可更换内核的序号    gedit /boot/grub/grub.cfg查询已安装的内核和内核的序号.找到文件中的menuentry (图中在一大堆fi-else底下)menuentry底下还有 ...

  4. SpringMVC的表单组件、国际化

    spring mvc 的表单标签库 1.Student实体类 package com.southwind.POJO; import lombok.Data; @Data public class St ...

  5. 基于minikube快速搭建kubernetes单节点环境

    一.说明 本文主要介绍在 Centos7 环境下基于 Minikube 来快速部署 Kubernetes 单节点集群环境,并在浏览器上访问部署在 k8s 上的 dashboard 服务. 二.Mini ...

  6. bat想要写一个卸载软件的脚本,最后宣布失败[未完待续...]

    find 的用法:双引号,搜索内容是英文也要用双引号 C:\Users\clouder\Desktop\yanna>find '小智' products.txt FIND: 参数格式不正确 C: ...

  7. P4238 【模板】多项式乘法逆

    #include <cstdio> #include <iostream> #define re register using namespace std; typedef l ...

  8. 了解舵机以及MG996R的控制方法

    了解舵机以及MG996R的控制方法 1.舵机基础知识: 舵机是遥控航空.航天模型控制动作,改变方向的重要组成部件,舵机是一种位置(角度)伺服的驱动器. 舵机主要适用于那些需要角度不断变化并可以保持的控 ...

  9. LeetCode-1669 合并两个链表

    来源:力扣(LeetCode)链接:https://leetcode.cn/problems/merge-in-between-linked-lists 题目描述 给你两个链表 list1 和 lis ...

  10. Python实战项目6-后端多方式登录接口/手机登录接口

    为开源项目共享代码 步骤: 1先fork开源项目 2clone下来,修改代码,进行提交 3提交pr,等作者同意 Pycharm 使用Git 右键文件会列出Git命令 登录注册功能分析 多方式登录接口: ...