hdu4547

CD操作

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)

Total Submission(s): 1010    Accepted Submission(s): 275

Problem Description
  在Windows下我们可以通过cmd运行DOS的部分功能,其中CD是一条很有意思的命令,通过CD操作,我们可以改变当前目录。

  这里我们简化一下问题,假设只有一个根目录,CD操作也只有两种方式:

  

  1. CD 当前目录名\...\目标目录名 (中间可以包含若干目录,保证目标目录通过绝对路径可达)

  2. CD .. (返回当前目录的上级目录)

  

  现在给出当前目录和一个目标目录,请问最少需要几次CD操作才能将当前目录变成目标目录?
 
Input
输入数据第一行包含一个整数T(T<=20),表示样例个数;

每个样例首先一行是两个整数N和M(1<=N,M<=100000),表示有N个目录和M个询问;

接下来N-1行每行两个目录名A B(目录名是只含有数字或字母,长度小于40的字符串),表示A的父目录是B。

最后M行每行两个目录名A B,表示询问将当前目录从A变成B最少要多少次CD操作。

数据保证合法,一定存在一个根目录,每个目录都能从根目录访问到。
 
Output
请输出每次询问的结果,每个查询的输出占一行。
 
Sample Input
2
3 1
B A
C A
B C 3 2
B A
C B
A C
C A
 
Sample Output
2
1
2
 

方法一:

1700ms

#include"stdio.h"
#include"string.h"
#include"stdlib.h"
#define M 100009
#include"string"
#include"map"
#include"iostream"
using namespace std;
typedef struct st
{
int u,v,next,w;
}E[M*3];
E edge,edge1;
int dis[M],head[M],head1[M],t,t1,use[M],in[M];
int f[M];
int finde(int x)
{
if(x!=f[x])
f[x]=finde(f[x]);
return f[x];
}
void make(int u,int v)
{
int x=finde(u);
int y=finde(v);
if(x!=y)
f[x]=y;
}
void init()
{
t=t1=0;
memset(head,-1,sizeof(head));
memset(head1,-1,sizeof(head1));
}
void add(int u,int v)
{
edge[t].u=u;
edge[t].v=v;
edge[t].next=head[u];
head[u]=t++;
}
void add1(int u,int v,int w)
{
edge1[t1].u=u;
edge1[t1].v=v;
edge1[t1].w=w;
edge1[t1].next=head1[u];
head1[u]=t1++;
}
void dfs(int u)
{
use[u]=1;
int i;
for(i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].v;
if(!use[v])
{
dis[v]=dis[u]+1;
dfs(v);
f[v]=u;
make(u,v);
}
}
for(i=head1[u];i!=-1;i=edge1[i].next)
{
int v=edge1[i].v;
if(use[v])
{
edge1[i].w=edge1[i^1].w=f[finde(v)];
}
}
}
int main()
{
int T,i,m,n,x,y;
char ch1[60],ch2[60];
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
map<string,int>mp;
int k=1;
init();
memset(in,0,sizeof(in));
for(i=1;i<n;i++)
{
scanf("%s%s",ch1,ch2);
if(mp[ch1]==0)
{
x=k;
mp[ch1]=k++;
}
else
x=mp[ch1];
if(mp[ch2]==0)
{
y=k;
mp[ch2]=k++;
}
else
y=mp[ch2];
add(y,x);
in[x]++;
}
while(m--)
{
scanf("%s%s",ch1,ch2);
add1(mp[ch1],mp[ch2],0);
add1(mp[ch2],mp[ch1],0);
}
memset(use,0,sizeof(use));
memset(dis,0,sizeof(dis));
for(i=1;i<=n;i++)
f[i]=i;
for(i=1;i<=n;i++)
{
if(!in[i])
dfs(i);
}
for(i=0;i<t1;i+=2)
{
int u=edge1[i].u;
int v=edge1[i].v;
int mid=edge1[i].w;
int p;
if(v==mid)
p=0;
else
p=1;
printf("%d\n",dis[u]-dis[mid]+p);
}
}
}

方法二:

2700ms

#include"stdio.h"
#include"string.h"
#include"map"
#include"iostream"
#include"queue"
using namespace std;
#define M 100006
int dis[M];
int pre[M];
int rank[M],use[M],t,head[M];
int targan(int a,int b)
{
if(a==b)
return a;
else if(rank[a]>rank[b])
return targan(pre[a],b);
else
return targan(a,pre[b]);
}
struct st
{
int u,v,next;
}edge[M*3];
void init()
{
t=0;
memset(head,-1,sizeof(head)); }
void add(int u,int v)
{
edge[t].u=u;
edge[t].v=v;
edge[t].next=head[u];
head[u]=t++;
}
void bfs(int s)
{
queue<int>q;
memset(use,0,sizeof(use));
use[s]=1;
memset(rank,0,sizeof(rank));
q.push(s);
while(!q.empty())
{
int u=q.front();
q.pop();
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].v;
if(!use[v])
{
use[v]=1;
rank[v]=rank[u]+1;
q.push(v);
}
}
}
}
int main()
{
int w;
scanf("%d",&w);
while(w--)
{
map<string,int>mp;
int n,m,i;
char ch1[444],ch2[444];
init();
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)
pre[i]=i;
int t=1;
for(i=1;i<n;i++)
{
scanf("%s%s",ch1,ch2);
if(!mp[ch1])
mp[ch1]=t++;
if(!mp[ch2])
mp[ch2]=t++;
pre[mp[ch1]]=mp[ch2];
dis[mp[ch1]]=1;
add(mp[ch2],mp[ch1]);
}
int tep=-1;
for(i=1;i<=n;i++)
if(pre[i]==i)
tep=i;
bfs(tep);
while(m--)
{
scanf("%s%s",ch1,ch2);
int ans=targan(mp[ch1],mp[ch2]);
if(ans!=mp[ch2])
printf("%d\n",rank[mp[ch1]]-rank[ans]+1);
else
printf("%d\n",rank[mp[ch1]]-rank[ans]);
}
}
return 0; }

LCA(离线算法)的更多相关文章

  1. Tarjan的LCA离线算法

    LCA(Least Common Ancestors)是指树结构中两个结点的最低的公共祖先.而LCA算法则是用于求两个结点的LCA.当只需要求一对结点的LCA时,我们很容易可以利用递归算法在O(n)的 ...

  2. Closest Common Ancestors---poj1470(LCA+离线算法)

    题目链接:http://poj.org/problem?id=1470 题意是给出一颗树,q个查询,每个查询都是求出u和v的LCA:    以下是寻找LCA的预处理过程: void LCA(u){ f ...

  3. HDU 2874 Connections between cities(LCA离线算法实现)

    http://acm.hdu.edu.cn/showproblem.php?pid=2874 题意: 求两个城市之间的距离. 思路: LCA题,注意原图可能不连通. 如果不了解离线算法的话,可以看我之 ...

  4. LCA离线算法Tarjan详解

    离线算法也就是需要先把所有查询给保存下来,最后一次输出结果. 离线算法是基于并查集实现的,首先就是初始化P[i] = i. 接下来对于每个点进行dfs: ①首先判断是否有与该点有关的查询,如果当前该点 ...

  5. poj1330+hdu2586 LCA离线算法

    整整花了一天学习了LCA,tarjan的离线算法,就切了2个题. 第一题,给一棵树,一次查询,求LCA.2DFS+并查集,利用深度优先的特点,回溯的时候U和U的子孙的LCA是U,U和U的兄弟结点的子孙 ...

  6. 距离LCA离线算法Tarjan + dfs + 并查集

    距离B - Distance in the Tree 还是普通的LCA但是要求的是两个节点之间的距离,学到了一些 一开始我想用带权并查集进行优化,但是LCA合并的过程晚于离线计算的过程,所以路径长度会 ...

  7. LCA离线算法Tarjan的模板

    hdu 2586:题意:输入n个点的n-1条边的树,m组询问任意点 a b之间的最短距离 思路:LCA中的Tarjan算法,RMQ还不会.. #include <stdio.h> #inc ...

  8. HDU 2874 LCA离线算法 tarjan算法

    给出N个点,M条边.Q次询问 Q次询问每两点之间的最短距离 典型LCA 问题   Marjan算法解 #include "stdio.h" #include "strin ...

  9. POJ1986 DistanceQueries 最近公共祖先LCA 离线算法Tarjan

    这道题与之前那两道模板题不同的是,路径有了权值,而且边是双向的,root已经给出来了,就是1,(这个地方如果还按之前那样来计算入度是会出错的.数据里会出现多个root...数据地址可以在poj的dis ...

  10. 1128 - Greatest Parent---LightOj(LCA+离线算法)

    题目链接:http://lightoj.com/volume_showproblem.php?problem=1128 给你一颗树,树的每个节点都有一个权值,树根是节点0,权值为1,树中每个节点的权值 ...

随机推荐

  1. jQuery客户端分页

    01 <script src="/js/jquery-1.4.1.js" type="text/javascript"></script> ...

  2. 关于Unity中UI中的Mask组件、Text组件和布局

    一.Mask组件 遮罩,Rect Mask矩形Mask(Rect Mask2D组件),图片Mask(Mask组件)(图片Mask的透明度不为0的部分显示子图片,为0的部分不显示子图片) Rect Ma ...

  3. 【案例分析】Linux下怎样查看port占用情况

    作者:zhanhailiang 日期:2014-11-08 基于express写一个測试server代码例如以下,可是执行失败,报"listen EADDRINUSE".字面上理解 ...

  4. circso 对数据进行可视化

    circos可以用来绘制圈图,能够对染色体上的数据进行可视化,首先需要一个染色体的文件 染色体的文件如下,每列之间空格分隔 chr - chr1 chr1 chr - chr2 chr2 chr - ...

  5. Qt 定时器Timer使用

    From: http://dragoon666.blog.163.com/blog/static/107009194201092602326598/ 1.新建Gui工程,在主界面上添加一个标签labe ...

  6. 【Java面试题】35 List, Set, Map是否继承自Collection接口?

    Collection是最基本的集合接口,声明了适用于JAVA集合(只包括Set和List)的通用方法. Set 和List 都继承了Conllection:Set具有与Collection完全一样的接 ...

  7. uniqid,md5,microtime

    <?php header("content-type:text/html;charset=utf-8"); $str = uniqid(md5(microtime(true) ...

  8. PHP简单的图片上传

    <!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  9. asp.net截屏功能实现截取web页面

    using System.Drawing;  //打开该页面 System.Diagnostics.Process.Start("IEXPLORE.EXE", "http ...

  10. VMWare虚拟机提示:打不开磁盘…或它所依赖的某个快照磁盘,开启模块DiskEarly的操作失败,未能启动虚拟机

    将电脑上存在的虚拟机复制一份后打开运行,弹出错误提示: 打不开磁盘…或它所依赖的某个快照磁盘,开启模块DiskEarly的操作失败,未能启动虚拟机. 解决方法如下: 打开存放虚拟机系统硬盘的所在文件夹 ...