题意:在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. 编写pl/sql时,报错

    /* 写一个简单的PL/SQL */ declare a ; b ; c number; begin c:=(a+b)/(a-b); dbms_output.put_line(c); exceptio ...

  2. 使用solr批量导入mysql数据库,以及Unable to read: dataimport.properties等坑

    折腾了一下午终于成功了!先放一张成功图: 成功把mysql的数据添加进去了,我这里是整合了tomcat9,整合步骤挺麻烦的,百度一大堆! 这里主要介绍批量导入数据,这里有些坑,所以记录一下: 步骤: ...

  3. Linux USB驱动框架分析(2)【转】

    转自:http://blog.chinaunix.net/uid-23046336-id-3243543.html   看了http://blog.chinaunix.net/uid-11848011 ...

  4. 二十一、springboot之定制URL匹配规则(项目中遇到的问题:get方式传参,带有小数点,被忽略)

    一.问题描述: get方式传参,在传送价格,积分时(带有小数点),debug后台微服务接受到的参数,却不带小数点,如:price是0.55,后台接受后却是0 二.解决 在WebConfiguratio ...

  5. sublime Text快捷键(超级全)

    sublime Text快捷键(超级全) Ctrl+Shift+P:打开命令面板 Ctrl+P:搜索项目中的文件 Ctrl+G:跳转到第几行 Ctrl+W:关闭当前打开文件 Ctrl+Shift+W: ...

  6. ubuntu下将程序挂后台命令

    ubuntu下将程序挂后台命令 nohup python -u main.py > test.out 2>&1 & ubunut下查看后台进程 jobs -l

  7. python随笔(二)

    range(2,10):不包括10 range(2,10,3):步长为3 range(10,2,-1):从10到2,步长-1.

  8. POJ 2195 Going Home(KM算法模板)

    题目链接:http://poj.org/problem?id=2195 题目大意: 给定一个N*M的地图,地图上有若干个man和house,且man与house的数量一致. man每移动一格需花费$1 ...

  9. tp杂记

    /** php中的大U函数三个参数: U('ajaxDelPic') ==> /index.php/Admin/Goods/ajaxDelPic.html U('ajaxDelPic?id=1' ...

  10. Java事务管理之Hibernate

    环境与版本 Hibernate 版本:Hibernate 4.2.2 (下载后的文件名为hibernate-release-4.2.2.Final.zip,解压目录hibernate-release- ...