时间限制:10000ms
单点时限:1000ms
内存限制:256MB

描述

上上回说到,小Hi和小Ho用非常拙劣——或者说粗糙的手段山寨出了一个神奇的网站,这个网站可以计算出某两个人的所有共同祖先中辈分最低的一个是谁。远在美国的他们利用了一些奇妙的技术获得了国内许多人的相关信息,并且搭建了一个小小的网站来应付来自四面八方的请求。

但正如我们所能想象到的……这样一个简单的算法并不能支撑住非常大的访问量,所以摆在小Hi和小Ho面前的无非两种选择:

其一是购买更为昂贵的服务器,通过提高计算机性能的方式来满足需求——但小Hi和小Ho并没有那么多的钱;其二则是改进他们的算法,通过提高计算机性能的利用率来满足需求——这个主意似乎听起来更加靠谱。

于是为了他们第一个在线产品的顺利运作,小Hi决定对小Ho进行紧急训练——好好的修改一番他们的算法。

而为了更好的向小Ho讲述这个问题,小Hi将这个问题抽象成了这个样子:假设现小Ho现在知道了N对父子关系——父亲和儿子的名字,并且这N对父子关系中涉及的所有人都拥有一个共同的祖先(这个祖先出现在这N对父子关系中),他需要对于小Hi的若干次提问——每次提问为两个人的名字(这两个人的名字在之前的父子关系中出现过),告诉小Hi这两个人的所有共同祖先中辈分最低的一个是谁?

提示一:老老实实分情况讨论就不会出错的啦!

提示二:并查集其实长得很像一棵树你们不觉得么?

输入

每个测试点(输入文件)有且仅有一组测试数据。

每组测试数据的第1行为一个整数N,意义如前文所述。

每组测试数据的第2~N+1行,每行分别描述一对父子关系,其中第i+1行为两个由大小写字母组成的字符串Father_i, Son_i,分别表示父亲的名字和儿子的名字。

每组测试数据的第N+2行为一个整数M,表示小Hi总共询问的次数。

每组测试数据的第N+3~N+M+2行,每行分别描述一个询问,其中第N+i+2行为两个由大小写字母组成的字符串Name1_i, Name2_i,分别表示小Hi询问中的两个名字。

对于100%的数据,满足N<=10^5,M<=10^5, 且数据中所有涉及的人物中不存在两个名字相同的人(即姓名唯一的确定了一个人),所有询问中出现过的名字均在之前所描述的N对父子关系中出现过,第一个出现的名字所确定的人是其他所有人的公共祖先。

输出

对于每组测试数据,对于每个小Hi的询问,按照在输入中出现的顺序,各输出一行,表示查询的结果:他们的所有共同祖先中辈分最低的一个人的名字。

样例输入
4
Adam Sam
Sam Joey
Sam Micheal
Adam Kevin
3
Sam Sam
Adam Sam
Micheal Kevin
样例输出
Sam
Adam
Adam

tarjan LCA:

tarjan算法不只是缩点算法呀!

DFS由深到浅处理每个子树,用并查集维护整棵子树的公共祖先。

 /*by SilverN*/
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<vector>
#include<map>
using namespace std;
const int mxn=;
struct edge{
int v,nxt;
}e[mxn];
int hd[mxn],mct=;
void add_edge(int u,int v){
e[++mct].v=v;e[mct].nxt=hd[u];hd[u]=mct;
return;
}
//
vector<int>query[mxn];
map<string,int>id;
int idcnt=;
char s[mxn][];
int ans[mxn];
char ql[mxn][],qr[mxn][];
//
int n,m;
//
int fa[mxn];
void init(){for(int i=;i<=n;i++)fa[i]=i;return;}
int find(int x){
if(fa[x]==x)return x;
return fa[x]=find(fa[x]);
}
//
void DFS(int u,int ff){
fa[u]=u;
int i,j;
for(i=hd[u];i;i=e[i].nxt){
DFS(e[i].v,u);
}
for(i=;i<query[u].size();++i){
int v=query[u][i];
int tmp;
if(u==id[ql[v]])tmp=id[qr[v]];
else tmp=id[ql[v]];
if(!fa[tmp])continue;
ans[v]=find(tmp);
}
fa[u]=find(fa[ff]);
}
int main(){
scanf("%d",&n);
int i,j;
char s1[],s2[];
for(i=;i<=n;i++){
scanf("%s%s",s1,s2);
if(!id[s1]){
id[s1]=++idcnt;
memcpy(s[idcnt],s1,sizeof s1);
}
if(!id[s2]){
id[s2]=++idcnt;
memcpy(s[idcnt],s2,sizeof s2);
}
add_edge(id[s1],id[s2]);
}
scanf("%d",&m);
for(i=;i<=m;i++){
scanf("%s%s",ql[i],qr[i]);
query[id[ql[i]]].push_back(i);
query[id[qr[i]]].push_back(i);
}
memset(fa,,sizeof fa);
DFS(,);
for(i=;i<=m;i++){
printf("%s\n",s[ans[i]]);
}
return ;
}

Hihocoder #1067 : 最近公共祖先·二的更多相关文章

  1. hihoCoder #1067 : 最近公共祖先·二 [ 离线LCA tarjan ]

    传送门: #1067 : 最近公共祖先·二 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 上上回说到,小Hi和小Ho用非常拙劣——或者说粗糙的手段山寨出了一个神奇的网站 ...

  2. HihoCoder 1067 最近公共祖先(ST离线算法)

    最近公共祖先·二 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 上上回说到,小Hi和小Ho用非常拙劣——或者说粗糙的手段山寨出了一个神奇的网站,这个网站可以计算出某两个 ...

  3. hihoCoder week15 最近公共祖先·二

    tarjan求lca  就是dfs序中用并查集维护下,当访问到询问的第二个点u的时候  lca就是第一点的find(fa[v]) fa[v] = u; // 当v为u的儿子 且 v已经dfs完毕 #i ...

  4. hihocoder1067 最近公共祖先·二(tarjin算法)(并查集)

    #1067 : 最近公共祖先·二 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 上上回说到,小Hi和小Ho用非常拙劣——或者说粗糙的手段山寨出了一个神奇的网站,这个网站 ...

  5. 【HIHOCODER 1067】最近公共祖先·二(LCA)

    描述 上上回说到,小Hi和小Ho用非常拙劣--或者说粗糙的手段山寨出了一个神奇的网站,这个网站可以计算出某两个人的所有共同祖先中辈分最低的一个是谁.远在美国的他们利用了一些奇妙的技术获得了国内许多人的 ...

  6. 学习LCA( 最近公共祖先·二)

    http://poj.org/problem?id=1986 离线找u,v之间的最小距离(理解推荐) #include<iostream> #include<cstring> ...

  7. hihocoder #1062 : 最近公共祖先·一(小数据量 map+set模拟+标记检查 *【模板】思路 )

    #1062 : 最近公共祖先·一 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Ho最近发现了一个神奇的网站!虽然还不够像58同城那样神奇,但这个网站仍然让小Ho乐在 ...

  8. hihoCoder 1062 最近公共祖先·一 最详细的解题报告

    题目来源:最近公共祖先·一 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 题目描述 小Ho最近发现了一个神奇的网站!虽然还不够像58同城那样神奇,但这个网站仍然让小Ho乐在其 ...

  9. 【hihoCoder第十五周】最近公共祖先·二

    老实说我没有读题,看见标题直接就写了,毕竟hiho上面都是裸的算法演练. 大概看了下输入输出,套着bin神的模板,做了个正反map映射,但是怎么都得不了满分.等这周结束后,找高人询问下trick. 若 ...

随机推荐

  1. AJPFX辨析Java中运算符 ++ 和 += 的区别

    我们都知道Java中 ++ 和 +=1  都是把数字增加一后,把值赋给左边,那二者有什么区别呢? i+=1 运行的底层Heap申请一个区域存放i,在数据区域开劈一个区域存放1,2个内存段被数据被送入到 ...

  2. AJPFX关于一维数组的声明与初始化

    一维数组:可以理解为一列多行.类型相同的数据,其中每个数据被称为数组元素:一维数组的声明方式:                type varName[]; 或 type[] varName;(推荐) ...

  3. Javaweb学习笔记8—DBUtils工具包

    今天来讲javaweb的第8阶段学习. DBUtils技术,DBUtils是我们操作数据库很常用的功能,虽然后期使用都是它的封装结果,但是也需要掌握. 老规矩,首先先用一张思维导图来展现今天的博客内容 ...

  4. 我来说说java的NIO

      Java NIO的出现旨在提高文件的读写速度,当然IO用NIO重新实过,所以我们不用显示的调用NIO也能享受这种高效的文件读写. Java NIO的高效得益于其两大"助手":C ...

  5. [Python學習筆記] 使用xlwings 插入註解 (forked 版本)

    到今天為止 xlwings 還沒有插入註解的功能 去原始開發者的 Github Pull Requests 他說之前有人有建議要加入這個功能 但他還沒更新~ 如果需要使用 Python 來插入註解的話 ...

  6. C++变量和基本类型

    1. 如何选择类型的准则 当明确知晓数值不可能为负的时候,应该选择无符号类型. 使用int执行整数运算的时候,在实际应用中,short常常显得太小而long一般和int有一样的尺寸,如果数值超过了in ...

  7. c++的if语句中的110为什么不等于110?

    从上图可以看出,当表达式1.1*x被直接放进if的判断括号中时1.1*x不等于y,但是将1.1*x赋值给z时,z与y相等,这是为什么?(以下为不等价时的代码) #include<stdio.h& ...

  8. CF633H Fibonacci-ish II

    题目描述 题解: 坑题搞了三天. 莫队+线段树. 还有一些和斐波那契数列有关的性质. 首先答案是$a_1f_1+a_2f_2+…+a_nf_n$, 考虑插进去一个元素对答案产生的影响. 比如插进去一个 ...

  9. <Spring Cloud>入门三 Ribbon

    1.Ribbon 客户端软负载均衡组件 1.1配置 搭建了三个消费者供客户端调用: 1.修改yml eureka: client: service-url: defaultZone: http://e ...

  10. Linux系统权限

    目 录 第1章 权限描述    1 1.1 权限描述    1 1.2 文件权限对应表    1 1.3 三种角色    1 1.4 文件和用户以及组之间的关系    1 第2章 修改权限命令chmo ...