hdu 4547 LCA **
题意:在Windows下我们可以通过cmd运行DOS的部分功能,其中CD是一条很有意思的命令,通过CD操作,我们可以改变当前目录。
这里我们简化一下问题,假设只有一个根目录,CD操作也只有两种方式:
1. CD 当前目录名\...\目标目录名 (中间可以包含若干目录,保证目标目录通过绝对路径可达)
2. CD .. (返回当前目录的上级目录)
现在给出当前目录和一个目标目录,请问最少需要几次CD操作才能将当前目录变成目标目录?
链接:点我
先返回到根目录,然后直接前进到目标目录
#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 **的更多相关文章
- hdu 4547(LCA)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4547 思路:这题的本质还是LCA问题,但是需要注意的地方有: 1.如果Q中u,v的lca为u,那么只需 ...
- 【HDU 4547 CD操作】LCA问题 Tarjan算法
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4547 题意:模拟DOS下的cd命令,给出n个节点的目录树以及m次查询,每个查询包含一个当前目录cur和 ...
- HDU 4547 CD操作 (LCA最近公共祖先Tarjan模版)
CD操作 倍增法 https://i.cnblogs.com/EditPosts.aspx?postid=8605845 Time Limit : 10000/5000ms (Java/Other) ...
- lca讲解 && 例题 HDU - 4547
一. 最普通的找树中两个点x,y最近公共祖先: 在进行lca之前我们要先对这一颗树中的每一个点进行一个编号,像下图一样.这个编号就是tarjan算法中的dfn[]数组 这样的话我们可以在跑tarjan ...
- HDU 3078 (LCA+树链第K大)
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3078 题目大意:定点修改.查询树中任意一条树链上,第K大值. 解题思路: 先用离线Tarjan把每个 ...
- HDU 2586 (LCA模板题)
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=2586 题目大意:在一个无向树上,求一条链权和. 解题思路: 0 | 1 / \ 2 3 ...
- [hdu 2586]lca模板题(在线+离线两种版本)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2586 在线版本: 在线方法的思路很简单,就是倍增.一遍dfs得到每个节点的父亲,以及每个点的深度.然后 ...
- hdu 2874(LCA)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2874 思路:近乎纯裸的LCA,只是题目给出的是森林,就要判断是否都在同一颗树上,这里我们只需判断两个子 ...
- HDU 2586 ( LCA/tarjan算法模板)
链接:http://acm.hdu.edu.cn/showproblem.php?pid=2586 题意:n个村庄构成一棵无根树,q次询问,求任意两个村庄之间的最短距离 思路:求出两个村庄的LCA,d ...
随机推荐
- 对web标准的理解,以及对w3c组织的认识
(1)web标准规范要求,书写标签必须闭合.标签小写.不乱嵌套,可提高搜索机器人对网页内容的搜索几率.--- SEO(2)建议使用外链css和js脚本,从而达到结构与行为.结构与表现的分离,提高页面的 ...
- 加密文件之Java改进版
对应Python版:加密文件之Python版Java版比Python版要快得多,两个版本不在一个量级上.在加密解密1G大文件时,Java版花费的时间是秒级,而Python版花费的时间是10分钟级. i ...
- gc overhead limit exceeded内存问题
gc overhead limit exceeded 当出现这种问题的时候一般有两种思路 一.修改idea或者eclipse中的配置文件,将内存调到1024即可 二.在代码中通过system.gc 手 ...
- Java项目打war包的方法
我们可以运用DOS命令来手工打war包: 首先,打开DOS命令行,敲入“jar”,我们发现它提示不是内部或外部的命令这样的错误,这时八成是你的JAVA环境没有配置好,我们可以用JAVA_HOME方式或 ...
- Shell编程学习2--命令大全
Linux中有很多的命令,这些命令可分分为10类(具体参见[1]): 1) 文件管理; 2) 文档编辑; 3) 文件传输; 4) 磁盘管理; 5) 磁盘维护; 6) 网络通讯; 7) 系统管理; 8) ...
- 工具类DateHandler
package com.ctid.rachel.core.util; import java.math.BigDecimal;import java.util.Calendar;import java ...
- python_Appium测试环境搭建
Android环境搭建 移动端Appium环境部署比Web的selenium环境稍微复杂一些,如用python编写测试用例脚本或者开发测试框架以及UI自动化操作方法是一样的,基本是通用.因两者都是基于 ...
- LeetCode691. Stickers to Spell Word
We are given N different types of stickers. Each sticker has a lowercase English word on it. You wou ...
- CCF CSP 201403-3 命令行选项
CCF计算机职业资格认证考试题解系列文章为meelo原创,请务必以链接形式注明本文地址 CCF CSP 201403-3 命令行选项 问题描述 请你写一个命令行分析程序,用以分析给定的命令行里包含哪些 ...
- 2017 Tag Cloud
距离上一篇随笔已经过去了三年多,惊讶地发现我还有个博客在这里 :) 越来越懒,这三年多就用下面这个tag cloud来总结好了