传送门

没啥好说的。就是一个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 = 0, f = 1; char ch = getchar();while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); }while (ch >= '0' && ch <= '9') { x = x * 10 + ch - 48; ch = getchar(); }return x * f;
}
const int N = 1e5 + 10;
struct Edge { int v, next; } edge[N];
int n, m, cnt, head[N], fa[N], degree[N], lca[N][17], dep[N];
bool vis[N];
map<string, int> mp;
int tol;inline void init() { memset(head, 0, sizeof(head));memset(fa, 0, sizeof(fa));memset(vis, 0, sizeof(vis));memset(degree, 0, sizeof(degree));memset(lca, 0, sizeof(lca));cnt = tol = 0;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] = 1;lca[u][0] = fa[u];for (int i = 1; i <= 16; i++) lca[u][i] = lca[lca[u][i-1]][i-1];for (int i = head[u]; i; i = edge[i].next) {int v = edge[i].v;if (vis[v]) continue;dep[v] = dep[u] + 1;fa[v] = u;dfs(v); }
}int Lca(int u, int v) {if (dep[u] < dep[v]) swap(u, v);for (int i = 16; i >= 0; i--) if (dep[lca[u][i]] >= dep[v]) u = lca[u][i];if (u == v) return u;for (int i = 16; i >= 0; i--) if (lca[u][i] != lca[v][i]) u = lca[u][i], v = lca[v][i];return lca[u][0];
}int main() {int T = read();while (T--) {init();n = read(); m = read();for (int i = 0; i < n - 1; i++) {string a, b;cin >> a >> b;int u = index(a), v = index(b);addedge(v, u);degree[u]++;}int root = 0;for (int i = 1; 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 ? 0 : 1));}}  return 0;
}

View Code

交了之后发现跑了两秒多

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

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <map>
#include <string>
#include <iostream>
using namespace std;inline int read() {int x = 0, f = 1; char ch = getchar();while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); }while (ch >= '0' && ch <= '9') { x = x * 10 + ch - 48; ch = getchar(); }return x * f;
}
const int N = 1e5 + 10;
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 * 2];
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, 0, sizeof(head));memset(qhead, 0, sizeof(qhead));memset(fa, 0, sizeof(fa));memset(vis, 0, sizeof(vis));memset(degree, 0, sizeof(degree));memset(dep, 0, sizeof(dep));memset(ans, 0, sizeof(ans));cnt = qcnt = tol = 0;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] = 1;for (int i = head[u]; i; i = edge[i].next) {int v = edge[i].v;if (vis[v]) continue;dep[v] = dep[u] + 1;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 = 0; i < n - 1; i++) {string a, b;cin >> a >> b;int u = index(a), v = index(b);addedge(v, u);degree[u]++;}int root = 0;for (int i = 1; i <= n; i++) if (!degree[i]) { root = i; break; }for (int i = 1; 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] = 0;dfs(root);for (int i = 1; i <= m; i++) {int u = qedge[2 * i].v, v = qedge[2 * i - 1].v;printf("%d\n", dep[u] - dep[ans[i]] + (ans[i] == v ? 0 : 1));}}return 0;
}

View Code

转载于:https://www.cnblogs.com/Mrzdtz220/p/10781335.html

HDU 4547 CD操作相关推荐

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

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

  2. HDU - 4547 CD操作(LCA模板)

    题目链接:点击查看 题目大意:给出一个层层嵌套的树状结构,可以从某一点通过一个操作直接到达任意一个子节点的位置,但如果要从某个节点到达其祖先节点需要一层一层往上爬,问若要从节点A到达节点B,需要多少步 ...

  3. hdu 4547(LCA+Tarjan)

    解题思路:很明显的LCA问题,用Tarjan离线算法即可.这里输入的可能是字符串,所以直接用map保存.此外,根据题意,这里需要稍稍有点变化,因为cd:a\b\c...这里是一步即可完成,所以在查询a ...

  4. hdu 2034 - 集合操作

    题意:集合A,B,计算集合差A-B(求只在集合A内的数) 解法: 选用STL内的集合set 1.建立set 2.关于集合的遍历,固定的格式: 用容器的iterator访问所有数据. 3.相应的用*it ...

  5. java调用cd传输_Java调用Linux命令(cd的处理)

    一.Java调用Linux系统的命令非常简单 这是一个非常常用的调用方法示例: 1 publicString executeLinuxCmd(String cmd) {2 System.out.pri ...

  6. java 执行cd_Java调用Linux命令(cd的处理)

    一.Java调用Linux系统的命令非常简单 这是一个非常常用的调用方法示例:public String executeLinuxCmd(String cmd) { System.out.printl ...

  7. 【Azure + Core】实现CI/CD(一)构建镜像并推送仓库

    (海上生明月,天涯共此时) 今天是农历八月十六,大家中秋节快乐! 放了三天假,和家人整理下屋子,打扫下卫生,闲着无聊就研究点儿新东西.最近一直再看DevOps相关的内容,自从开始学习Docker以来, ...

  8. 【壹个小技巧】一看就会的CI/CD :Github Actions

    什么是 CI/CD? 我这里先不说概念,先说一个平时开发的场景问题: 我们平时开发一个项目,经常会遇到这些"小"问题: 就是如何保证自己的项目是正确的,至少拿给别人的时候,可以编译 ...

  9. linux终端中出现 cd: OLDPWD 未设定 的提示

    是因为开始刚打开终端,第一次操作cd命令的原因. cd - 的作用是进入上一次cd操作的目录,而此时刚打开终端,第一次执行cd命令,本次命令是第一次cd的目录,没有上一次的目录. 看个例子:

最新文章

  1. 2-Runtime objc_object objc_class
  2. 多态amp;nbsp;OC——第十天
  3. 线上环境部署MongoDB的官方建议
  4. Java学习笔记_数组
  5. java 图片阴影_Java 为 PPT 中的图形添加阴影效果
  6. 对 app_offline.htm 的几点错误认识
  7. Mac 连过的 WiFi 怎么查密码?看这→
  8. 北京市延庆区谷歌卫星地图下载
  9. Robo3T操作MongoDB数据库常用命令
  10. 【软件测试基础理论知识】1.1.常见的软件开发模型之———瀑布模型、原型模型、快速原型模型
  11. 对于目标文件系统,文件过大怎么办
  12. 整车CAN网络拓扑图
  13. 同步机制应遵循的准则
  14. 杀毒软件工作原理 及 现在主要杀毒技术
  15. CSDN 下载 版块问题解决日志
  16. labview:一个采集数据的小程序
  17. 星之卡比机器人汉化_星之卡比:机械星球
  18. 西门子触摸屏数据历史数据记录_西门子触摸屏mp277历史数据丢失(免费技术支持)...
  19. 微信小程序_文档_08_组件_媒体组件_地图_画布_开放能力
  20. 程序员一定要打造一个专业的家庭开发工作站

热门文章

  1. html与css重置代码,发个自己的CSS重置基础代码
  2. java简单的文本编辑器_采用java语言如何建立一个简单的文本编辑器
  3. ios键盘弹回时顶上去得页面不会回来
  4. Web前端—— JQuery迷你版实现以及使用
  5. python pandas 对带时间序列的数据进行重采样处理
  6. 小甲鱼OD学习第18讲
  7. Atitit 基于dom的游戏引擎
  8. 复古多变“格子控”混搭 夏季继续魅力四射
  9. git 拉取代码失败
  10. Java的数据库编程之入门案例