题意:在Windows下我们可以通过cmd运行DOS的部分功能,其中CD是一条很有意思的命令,通过CD操作,我们可以改变当前目录。
  这里我们简化一下问题,假设只有一个根目录,CD操作也只有两种方式:
  
  1. CD 当前目录名\...\目标目录名 (中间可以包含若干目录,保证目标目录通过绝对路径可达)
  2. CD .. (返回当前目录的上级目录)
  
  现在给出当前目录和一个目标目录,请问最少需要几次CD操作才能将当前目录变成目标目录?

链接:点我

先返回到根目录,然后直接前进到目标目录

目录刚好成一颗树。
树有唯一的根结点。
每步操作可以到上一级目录,或者直接到下面的目录。
 
其实就是查询LCA
 
要求u->v
把u、v的lca求出来,设为tmp
那么肯定是先u->tmp->u
 
u->temp的步数刚好是他们的深度差,一个数组存深度差就可以了。
 
temp->v如果不相等就是一步,相等就是0步
  1. #include <iostream>
  2. #include <string.h>
  3. #include <algorithm>
  4. #include <queue>
  5. #include <map>
  6. #include <vector>
  7. #include <math.h>
  8. #include <string>
  9. #include <stdio.h>
  10. #include <math.h>
  11. using namespace std;
  12. #define MOD 1000000007
  13. #define pb(a) push_back(a)
  14. const int INF=0x3f3f3f3f;
  15. const double eps=1e-;
  16. typedef long long ll;
  17. #define cl(a) memset(a,0,sizeof(a))
  18. #define ts printf("*****\n");
  19. const int MAXN=;
  20. int n,m,ttt;
  21. int a[MAXN];
  22. int rmq[*MAXN];//rmq数组,就是欧拉序列对应的深度序列
  23. struct ST
  24. {
  25. int mm[*MAXN];
  26. int dp[*MAXN][];//最小值对应的下标
  27. void init(int n)
  28. {
  29. mm[] = -;
  30. for(int i = ;i <= n;i++)
  31. {
  32. mm[i] = ((i&(i-)) == )?mm[i-]+:mm[i-];
  33. dp[i][] = i;
  34. }
  35. for(int j = ; j <= mm[n];j++)
  36. for(int i = ; i + (<<j) - <= n; i++)
  37. dp[i][j] = rmq[dp[i][j-]] < rmq[dp[i+(<<(j-))][j-]]?dp[i][j-]:dp[i+(<<(j-))][j-];
  38. }
  39. int query(int a,int b)//查询[a,b]之间最小值的下标
  40. {
  41. if(a > b)swap(a,b);
  42. int k = mm[b-a+];
  43. return rmq[dp[a][k]] <= rmq[dp[b-(<<k)+][k]]?dp[a][k]:dp[b-(<<k)+][k];
  44. }
  45. };
  46. //边的结构体定义
  47. struct Edge
  48. {
  49. int to,next;
  50. };
  51. Edge edge[MAXN*];
  52. int tot,head[MAXN];
  53. int F[MAXN*];//欧拉序列,就是dfs遍历的顺序,长度为2*n-1,下标从1开始
  54. int P[MAXN];//P[i]表示点i在F中第一次出现的位置
  55. int cnt;
  56. ST st;
  57. void init()
  58. {
  59. tot = ;
  60. memset(head,-,sizeof(head));
  61. }
  62. void addedge(int u,int v)//加边,无向边需要加两次
  63. {
  64. edge[tot].to = v;
  65. edge[tot].next = head[u];
  66. head[u] = tot++;
  67. }
  68. void dfs(int u,int pre,int dep)
  69. {
  70. F[++cnt] = u;
  71. rmq[cnt] = dep;
  72. P[u] = cnt;
  73. for(int i = head[u];i != -;i = edge[i].next)
  74. {
  75. int v = edge[i].to;
  76. if(v == pre)continue;
  77. dfs(v,u,dep+);
  78. F[++cnt] = u;
  79. rmq[cnt] = dep;
  80. }
  81. }
  82. void LCA_init(int root,int node_num)//查询LCA前的初始化
  83. {
  84. cnt = ;
  85. dfs(root,root,);
  86. st.init(*node_num-);
  87. }
  88. int query_lca(int u,int v)//查询u,v的lca编号
  89. {
  90. return F[st.query(P[u],P[v])];
  91. }
  92. bool flag[MAXN];
  93. int Count_num[MAXN];
  94. int deep[MAXN];
  95. vector<int>vc[MAXN];
  96. map<string,int> mp;
  97. void bfs(int root)
  98. {
  99. cl(deep);
  100. int now,next;
  101. queue<int> q;
  102. q.push(root);
  103. deep[root]=;
  104. while(!q.empty())
  105. {
  106. now=q.front();
  107. q.pop();
  108. for(int i=;i<vc[now].size();i++)
  109. {
  110. next=vc[now][i];
  111. if(deep[next]==)
  112. {
  113. deep[next]=deep[now]+;
  114. q.push(next);
  115. }
  116. }
  117.  
  118. }
  119. }
  120. int main()
  121. {
  122. int i,j,k;
  123. #ifndef ONLINE_JUDGE
  124. freopen("1.in","r",stdin);
  125. #endif
  126. scanf("%d",&ttt);
  127. int ca=;
  128. while(ttt--)
  129. {
  130. scanf("%d%d",&n,&m);
  131. cl(flag);
  132. init();
  133. for(int i=;i<=n;i++)vc[i].clear();
  134. string u,v;
  135. mp.clear();
  136. int tot=;
  137. char s1[],s2[];
  138. for(i=;i<n-;i++)
  139. {
  140. cin>>u>>v;
  141. if(mp[u]==) mp[u]=++tot;
  142. if(mp[v]==) mp[v]=++tot;
  143. int a1=mp[u];
  144. int a2=mp[v];
  145. vc[a2].pb(a1);
  146. addedge(a2,a1);
  147. addedge(a1,a2);
  148. flag[a1]=;
  149. }
  150. int root;
  151. for(int i=;i<=n;i++)
  152. if(!flag[i])
  153. {
  154. root=i;
  155. break;
  156. }
  157. LCA_init(root,n);
  158. bfs(root);
  159. for(i=;i<m;i++)
  160. {
  161. cin>>u>>v;
  162. int a1=mp[u];
  163. int a2=mp[v];
  164. int temp=query_lca(a1,a2);
  165. int ans=deep[a1]-deep[temp];
  166. if(temp!=a2) ans++;
  167. printf("%d\n",ans);
  168. }
  169. }
  170. }

hdu 4547 LCA **的更多相关文章

  1. hdu 4547(LCA)

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

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

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

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

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

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

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

  5. HDU 3078 (LCA+树链第K大)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3078 题目大意:定点修改.查询树中任意一条树链上,第K大值. 解题思路: 先用离线Tarjan把每个 ...

  6. HDU 2586 (LCA模板题)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=2586 题目大意:在一个无向树上,求一条链权和. 解题思路: 0 | 1 /   \ 2      3 ...

  7. [hdu 2586]lca模板题(在线+离线两种版本)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2586 在线版本: 在线方法的思路很简单,就是倍增.一遍dfs得到每个节点的父亲,以及每个点的深度.然后 ...

  8. hdu 2874(LCA)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2874 思路:近乎纯裸的LCA,只是题目给出的是森林,就要判断是否都在同一颗树上,这里我们只需判断两个子 ...

  9. HDU 2586 ( LCA/tarjan算法模板)

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=2586 题意:n个村庄构成一棵无根树,q次询问,求任意两个村庄之间的最短距离 思路:求出两个村庄的LCA,d ...

随机推荐

  1. ubuntu网络连接:Ifupdown(eth0)的连接不能修改或删除

    今天其实遇到了三个问题,一个是ubuntu系统上的网络图标不见了,把网络图标弄出来以后有无法联网,联网成功却变成Ifupdown(eth0)的连接且不能修改或删除. 这里我只记录最后一个问题,前两个问 ...

  2. Next Permutation & Previous Permutation

    Next Permutation Given a list of integers, which denote a permutation. Find the next permutation in ...

  3. Sublime Text 3 注册码失效(被移除)解决方法

    最近Sublime Text 3 增加了注册码验证功能,如果你使用共享版本的注册码,可能会提示注册码失效,但是却可以正常激活. 只需要把下面的字段加入到你的hosts文件即可: 127.0.0.1 l ...

  4. 从一份配置清单详解 Nginx 服务器配置

      概述 在前面< Nginx 服务器开箱体验> 一文中我们从开箱到体验,感受了一下 Nginx 服务器的魅力.Nginx 是轻量级的高性能 Web 服务器,提供了诸如 HTTP 代理和反 ...

  5. IntelliJ IDEA 建空包合并问题。

    举例:我想在一个包下,创建2个空子包,这个时候,却无法再IDE里完成. 老是这样子,如果选中dff.sfsdf再右键 创建包的话,结局是再sfsdf下 又创建一个文件夹. 如果右键创建类的话,实际上在 ...

  6. Codeforces 552C Vanya and Scales(进制转换+思维)

    题目链接:http://codeforces.com/problemset/problem/552/C 题目大意:有101个砝码重量为w^0,w^1,....,w^100和一个重量为m的物体,问能否在 ...

  7. 【LOJ】 #2305. 「NOI2017」游戏

    题解 枚举x所在的地图的颜色,然后2-SAT建边 如果v所在的地图刚好是不能选的,那么u这边只能选另一种颜色 否则就是u的颜色到v的颜色 v的另一种颜色到u的另一种颜色 代码 #include < ...

  8. 【POJ】1286.Necklace of Beads

    题解 群论,我们只要找出所有的置换群的所有循环节 具体可参照算法艺术与信息学竞赛 旋转的置换有n个,每一个的循环节个数是gcd(N,i),i的范围是0到N - 1 翻转,对于奇数来说固定一个点,然后剩 ...

  9. USACO 4.3 Letter Game (字典树)

    Letter GameIOI 1995 Figure 1: Each of the 26 lowercase letters and its value Letter games are popula ...

  10. Failed to load JavaHL Library. SVN

    以前使用的电脑是32位的,安装的svn可以正常使用,但是现在的电脑室64位的,安装好svn后,把项目提交到svn的过程中,总是弹出来一个错误的对话框: Failed to load JavaHL Li ...