题意:在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步
 #include <iostream>
#include <string.h>
#include <algorithm>
#include <queue>
#include <map>
#include <vector>
#include <math.h>
#include <string>
#include <stdio.h>
#include <math.h>
using namespace std;
#define MOD 1000000007
#define pb(a) push_back(a)
const int INF=0x3f3f3f3f;
const double eps=1e-;
typedef long long ll;
#define cl(a) memset(a,0,sizeof(a))
#define ts printf("*****\n");
const int MAXN=;
int n,m,ttt;
int a[MAXN];
int rmq[*MAXN];//rmq数组,就是欧拉序列对应的深度序列
struct ST
{
int mm[*MAXN];
int dp[*MAXN][];//最小值对应的下标
void init(int n)
{
mm[] = -;
for(int i = ;i <= n;i++)
{
mm[i] = ((i&(i-)) == )?mm[i-]+:mm[i-];
dp[i][] = i;
}
for(int j = ; j <= mm[n];j++)
for(int i = ; i + (<<j) - <= n; i++)
dp[i][j] = rmq[dp[i][j-]] < rmq[dp[i+(<<(j-))][j-]]?dp[i][j-]:dp[i+(<<(j-))][j-];
}
int query(int a,int b)//查询[a,b]之间最小值的下标
{
if(a > b)swap(a,b);
int k = mm[b-a+];
return rmq[dp[a][k]] <= rmq[dp[b-(<<k)+][k]]?dp[a][k]:dp[b-(<<k)+][k];
}
};
//边的结构体定义
struct Edge
{
int to,next;
};
Edge edge[MAXN*];
int tot,head[MAXN];
int F[MAXN*];//欧拉序列,就是dfs遍历的顺序,长度为2*n-1,下标从1开始
int P[MAXN];//P[i]表示点i在F中第一次出现的位置
int cnt;
ST st;
void init()
{
tot = ;
memset(head,-,sizeof(head));
}
void addedge(int u,int v)//加边,无向边需要加两次
{
edge[tot].to = v;
edge[tot].next = head[u];
head[u] = tot++;
}
void dfs(int u,int pre,int dep)
{
F[++cnt] = u;
rmq[cnt] = dep;
P[u] = cnt;
for(int i = head[u];i != -;i = edge[i].next)
{
int v = edge[i].to;
if(v == pre)continue;
dfs(v,u,dep+);
F[++cnt] = u;
rmq[cnt] = dep;
}
}
void LCA_init(int root,int node_num)//查询LCA前的初始化
{
cnt = ;
dfs(root,root,);
st.init(*node_num-);
}
int query_lca(int u,int v)//查询u,v的lca编号
{
return F[st.query(P[u],P[v])];
}
bool flag[MAXN];
int Count_num[MAXN];
int deep[MAXN];
vector<int>vc[MAXN];
map<string,int> mp;
void bfs(int root)
{
cl(deep);
int now,next;
queue<int> q;
q.push(root);
deep[root]=;
while(!q.empty())
{
now=q.front();
q.pop();
for(int i=;i<vc[now].size();i++)
{
next=vc[now][i];
if(deep[next]==)
{
deep[next]=deep[now]+;
q.push(next);
}
} }
}
int main()
{
int i,j,k;
#ifndef ONLINE_JUDGE
freopen("1.in","r",stdin);
#endif
scanf("%d",&ttt);
int ca=;
while(ttt--)
{
scanf("%d%d",&n,&m);
cl(flag);
init();
for(int i=;i<=n;i++)vc[i].clear();
string u,v;
mp.clear();
int tot=;
char s1[],s2[];
for(i=;i<n-;i++)
{
cin>>u>>v;
if(mp[u]==) mp[u]=++tot;
if(mp[v]==) mp[v]=++tot;
int a1=mp[u];
int a2=mp[v];
vc[a2].pb(a1);
addedge(a2,a1);
addedge(a1,a2);
flag[a1]=;
}
int root;
for(int i=;i<=n;i++)
if(!flag[i])
{
root=i;
break;
}
LCA_init(root,n);
bfs(root);
for(i=;i<m;i++)
{
cin>>u>>v;
int a1=mp[u];
int a2=mp[v];
int temp=query_lca(a1,a2);
int ans=deep[a1]-deep[temp];
if(temp!=a2) ans++;
printf("%d\n",ans);
}
}
}

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. 2 - django-urls路由系统基本使用

    目录 1 路由系统(urls控制) 1.1 正则字符串参数 1.2 url的分组 1.2.1 无名分组 1.2.2 有名分组 1.3 URLconf 在什么上查找 1.4 include(路由分发) ...

  2. CentOS6.6中安装telnet

    一.查看本机是否安装telnet rpm -qa | grep telnet 如果什么都不显示.说明你没有安装telnet 二.开始安装 yum install xinetd yum install ...

  3. mysql5.7.10 源码编译安装记录 (centos6.4)【转】

    一.准备工作 1.1 卸载系统自带mysql 查看系统是否自带MySQL, 如果有就卸载了, 卸载方式有两种yum, rpm, 这里通过yum卸载 rpm -qa | grep mysql //查看系 ...

  4. C# WebClient进行FTP服务上传文件和下载文件

    定义WebClient使用的操作类: 操作类名称WebUpDown WebClient上传文件至Ftp服务: //// <summary> /// WebClient上传文件至Ftp服务 ...

  5. 编译器是如何实现32位整型的常量整数除法优化的?[C/C++]

    引子 在我之前的一篇文章[ ThoughtWorks代码挑战——FizzBuzzWhizz游戏 通用高速版(C/C++ & C#) ]里曾经提到过编译器在处理除数为常数的除法时,是有优化的,今 ...

  6. Python subprocess- call、check_call、check_output

    简介 subprocess模块用来创建新的进程,连接到其stdin.stdout.stderr管道并获取它们的返回码.subprocess模块的出现是为了替代如下旧模块及函数:os.system.os ...

  7. ASP .Net Core系统部署到 CentOS7 64 具体方案

    .Net Core 部署到 CentOS7 64 位系统中的步骤 1.安装工具 1.apache 2..Net Core(dotnet-sdk-2.0) 3.Supervisor(进程管理工具,目的是 ...

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

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

  9. UVA10212 【The Last Non-zero Digit.】

    暴力可做!!!(十秒还不打暴力!!!)暴力算阶乘边算边取余上代码 #include<iostream> #define int long long //开long long using n ...

  10. (二)SpringMVC控制器

    第一节:@RequestMapping请求映射 第二节:@RequestParam请求参数 第三节:ModelAndView返回模型和视图 第四节:SpringMVC对象属性自动封装 第五节:Spri ...