传送门

没啥好说的。就是一个LCA。

不过就是有从根到子树里任意一个节点只需要一次操作,特判一下LCA是不是等于v。相等的话不用走。否则就是1次操作。

主要是想写一下倍增的板子。

倍增基于二进制。暴力求LCA算法是while循环一步一步往上走。但其实是不需要的。

因为一个点走到它的任意一个祖先都是确定的步数。都可用表示成二进制数。

$lca_{u,i}$代表从$u$向上走$2^{i}$步到哪一个节点

预处理出来。让$u$,$v$同深度,再向上走$x-1$步就好了($x$代表两$u, v$到它们LCA的深度差)

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <map>
#include <string>
#include <iostream>
using namespace std; inline int read() {
int x = , f = ; char ch = getchar();
while (ch < '' || ch > '') { if (ch == '-') f = -; ch = getchar(); }
while (ch >= '' && ch <= '') { x = x * + ch - ; ch = getchar(); }
return x * f;
}
const int N = 1e5 + ;
struct Edge { int v, next; } edge[N];
int n, m, cnt, head[N], fa[N], degree[N], lca[N][], dep[N];
bool vis[N];
map<string, int> mp;
int tol; inline void init() {
memset(head, , sizeof(head));
memset(fa, , sizeof(fa));
memset(vis, , sizeof(vis));
memset(degree, , sizeof(degree));
memset(lca, , sizeof(lca));
cnt = tol = ;
mp.clear();
} inline void addedge(int u, int v) {
edge[++cnt].v = v; edge[cnt].next = head[u]; head[u] = cnt;
} int index(string s) {
if (mp.find(s) != mp.end()) return mp[s];
return mp[s] = ++tol;
} void dfs(int u) {
vis[u] = ;
lca[u][] = fa[u];
for (int i = ; i <= ; i++) lca[u][i] = lca[lca[u][i-]][i-];
for (int i = head[u]; i; i = edge[i].next) {
int v = edge[i].v;
if (vis[v]) continue;
dep[v] = dep[u] + ;
fa[v] = u;
dfs(v);
}
} int Lca(int u, int v) {
if (dep[u] < dep[v]) swap(u, v);
for (int i = ; i >= ; i--) if (dep[lca[u][i]] >= dep[v]) u = lca[u][i];
if (u == v) return u;
for (int i = ; i >= ; i--) if (lca[u][i] != lca[v][i]) u = lca[u][i], v = lca[v][i];
return lca[u][];
} int main() {
int T = read();
while (T--) {
init();
n = read(); m = read();
for (int i = ; i < n - ; i++) {
string a, b;
cin >> a >> b;
int u = index(a), v = index(b);
addedge(v, u);
degree[u]++;
}
int root = ;
for (int i = ; i <= n; i++) if (!degree[i]) { root = i; break; }
fa[root] = root;
dfs(root);
while (m--) {
string a, b;
cin >> a >> b;
int u = index(a), v = index(b);
int r = Lca(u, v);
printf("%d\n", dep[u] - dep[r] + (v == r ? : ));
}
}
return ;
}

交了之后发现跑了两秒多

然后写了发tarjan的 跑了1秒多 果然 tarjan的时间复杂度还是最优的

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <map>
#include <string>
#include <iostream>
using namespace std; inline int read() {
int x = , f = ; char ch = getchar();
while (ch < '' || ch > '') { if (ch == '-') f = -; ch = getchar(); }
while (ch >= '' && ch <= '') { x = x * + ch - ; ch = getchar(); }
return x * f;
}
const int N = 1e5 + ;
struct Edge { int v, next; } edge[N];
int cnt, head[N];
inline void addedge(int u, int v) {
edge[++cnt].v = v; edge[cnt].next = head[u]; head[u] = cnt;
}
struct Qedge { int v, next, num; } qedge[N * ];
int qcnt, qhead[N];
inline void addqedge(int u, int v, int num) {
qedge[++qcnt].v = v;
qedge[qcnt].next = qhead[u];
qhead[u] = qcnt;
qedge[qcnt].num = num;
}
int n, m, fa[N], degree[N], dep[N];
int ans[N];
bool vis[N];
map<string, int> mp;
int tol; inline void init() {
memset(head, , sizeof(head));
memset(qhead, , sizeof(qhead));
memset(fa, , sizeof(fa));
memset(vis, , sizeof(vis));
memset(degree, , sizeof(degree));
memset(dep, , sizeof(dep));
memset(ans, , sizeof(ans));
cnt = qcnt = tol = ;
mp.clear();
} int getfa(int x) { return x == fa[x] ? x : fa[x] = getfa(fa[x]); } int index(string s) {
if (mp.find(s) != mp.end()) return mp[s];
return mp[s] = ++tol;
} void dfs(int u) {
fa[u] = u;
vis[u] = ;
for (int i = head[u]; i; i = edge[i].next) {
int v = edge[i].v;
if (vis[v]) continue;
dep[v] = dep[u] + ;
dfs(v);
fa[v] = u;
}
for (int i = qhead[u]; i; i = qedge[i].next) {
int v = qedge[i].v;
if (vis[v]) {
ans[qedge[i].num] = getfa(v);
}
}
} int main() {
int T = read();
while (T--) {
init();
n = read(); m = read();
for (int i = ; i < n - ; i++) {
string a, b;
cin >> a >> b;
int u = index(a), v = index(b);
addedge(v, u);
degree[u]++;
}
int root = ;
for (int i = ; i <= n; i++) if (!degree[i]) { root = i; break; }
for (int i = ; i <= m; i++) {
string a, b;
cin >> a >> b;
int u = index(a), v = index(b);
addqedge(u, v, i);
addqedge(v, u, i);
}
dep[root] = ;
dfs(root);
for (int i = ; i <= m; i++) {
int u = qedge[ * i].v, v = qedge[ * i - ].v;
printf("%d\n", dep[u] - dep[ans[i]] + (ans[i] == v ? : ));
}
}
return ;
}

HDU 4547 CD操作的更多相关文章

  1. HDU 4547 CD操作 (LCA最近公共祖先Tarjan模版)

    CD操作 倍增法  https://i.cnblogs.com/EditPosts.aspx?postid=8605845 Time Limit : 10000/5000ms (Java/Other) ...

  2. 【HDU 4547 CD操作】LCA问题 Tarjan算法

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4547 题意:模拟DOS下的cd命令,给出n个节点的目录树以及m次查询,每个查询包含一个当前目录cur和 ...

  3. hdu 4547 LCA **

    题意:在Windows下我们可以通过cmd运行DOS的部分功能,其中CD是一条很有意思的命令,通过CD操作,我们可以改变当前目录. 这里我们简化一下问题,假设只有一个根目录,CD操作也只有两种方式: ...

  4. lca讲解 && 例题 HDU - 4547

    一. 最普通的找树中两个点x,y最近公共祖先: 在进行lca之前我们要先对这一颗树中的每一个点进行一个编号,像下图一样.这个编号就是tarjan算法中的dfn[]数组 这样的话我们可以在跑tarjan ...

  5. 【HDU 4547】 CD操作

    [题目链接] 点击打开链接 [算法] 分四种情况讨论 : 1. 当前目录和目标目录是同一目录,不需要变换,答案为0 2. 当前目录是目标目录的祖先,答案为当前目录的深度 - 目标目录的深度 3. 当前 ...

  6. hdu 4547(LCA)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4547 思路:这题的本质还是LCA问题,但是需要注意的地方有: 1.如果Q中u,v的lca为u,那么只需 ...

  7. hdu 5071 vector操作恶心模拟

    http://acm.hdu.edu.cn/showproblem.php?pid=5071 对于每一个窗口,有两个属性:优先级+说过的单词数,支持8个操作:新建窗口,关闭窗口并输出信息,聊天(置顶窗 ...

  8. 基于docker搭建Jenkins+Gitlab+Harbor+Rancher架构实现CI/CD操作

    一.各个组件的功能描述: Docker 是一个开源的应用容器引擎. Jenkis 是一个开源自动化服务器. (1).负责监控gitlab代码.gitlab中配置文件的变动: (2).负责执行镜像文件的 ...

  9. hdu 2034 - 集合操作

    题意:集合A,B,计算集合差A-B(求只在集合A内的数) 解法: 选用STL内的集合set 1.建立set 1: #include<set> 2:   3: set<int> ...

随机推荐

  1. Unity 虚拟摇杆的实现

    一般地,虚拟摇杆是放在UI层的. 所以先在Canvas建立一个空对象(这里被命名成MoveController),再在空对象里面放一个作为摇杆图片的Image. 然后通过覆盖重写UnityEngine ...

  2. 微信公众号开发C#系列-5、用户和用户组管理-支持同步

    1.概述 眼前时下流行的经济有个叫粉丝经济,粉丝带动收益.一个好运营良好的公众号肯定会有一大批的粉丝团,如何挖掘粉丝来产生效益,是微信营销的关键.微信公众号后台本身提供了粉丝(用户)与用户分组的管理, ...

  3. React引领未来用户界面——心莱科技内部直播分享会

    视频地址(请点开链接观看视频)https://v.qq.com/x/page/l08427ukdjo.html 本周,心莱科技在公司内部就开展了一场前端技术分享会,使用了直播模式进行分享,主要分享关于 ...

  4. spring transaction源码分析--事务架构

    1. 引言  事务特性 事务是并发控制的单元,是用户定义的一个操作序列.这些操作要么都做,要么都不做,是一个不可分割的工作单位.通过事务将逻辑相关的一组操作绑定在一起,以便服务器 保持数据的完整性.事 ...

  5. vscode local attach 和 remote debug

    VSCode是MS推出的一款免费的开源并跨平台的轻量级代码编辑器,内置Git和Debug等常用功能,强大的插件扩展功能以及简单的配置几乎可以打造成任意编程语言的IDE.本文简单聊一下其本地attach ...

  6. pytorch深度学习60分钟闪电战

    https://pytorch.org/tutorials/beginner/deep_learning_60min_blitz.html 官方推荐的一篇教程 Tensors #Construct a ...

  7. PC打开多个微信

    打开记事本 在哪个盘就打开哪个盘 例如我的D盘 输入这一串 D:CD 微信路径start WeChat.exe&WeChat.exe 保存然后改后缀名为.bat 然后运行 运行前要关掉之前开的 ...

  8. Yii2设计模式——Yii2中用到哪些设计模式?

    "Yii2设计模式"包含了两个方面的内容:1.设计模式,2.Yii2框架. <设计模式>一书虽然以JAVA语言来表达设计模式的思想,但是设计模式远不限制于某一种特定的语 ...

  9. HeadFirst设计模式读书笔记之策略模式

    1. 例子 1. 做一个鸭子模拟器,里面有很多不同的鸭子,有的可以游泳,有的可以睡觉,有的可以呱呱叫,一般套路是定义一个鸭子的超类,在 超类里定义睡觉,游泳,呱呱叫的方法,再让不同的鸭子子类继承这个超 ...

  10. 从零学习Fluter(八):Flutter的四种运行模式--Debug、Release、Profile和test以及命名规范

    从零学习Fluter(八):Flutter的四种运行模式--Debug.Release.Profile和test以及命名规范 好几天没有跟新我的这个系列文章,一是因为这两天我又在之前的基础上,重新认识 ...