题目1 : 近期公共祖先·二

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

描写叙述

上上回说到,小Hi和小Ho用很拙劣——或者说粗糙的手段山寨出了一个奇妙的站点,这个站点能够计算出某两个人的全部共同祖先中辈分最低的一个是谁。

远在美国的他们利用了一些奇异的技术获得了国内很多人的相关信息,而且搭建了一个小小的站点来应付来自四面八方的请求。

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

其一是购买更为昂贵的server。通过提高计算机性能的方式来满足需求——但小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

离线代码例如以下:

/*************************************************************************
> File Name: t.cpp
> Author: acvcla
> QQ:
> Mail: acvcla@gmail.com
> Created Time: 2014年10月16日 星期四 23时22分13秒
************************************************************************/
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<vector>
#include<cstring>
#include<map>
#include<queue>
#include<stack>
#include<string>
#include<cstdlib>
#include<ctime>
#include<set>
#include<math.h>
using namespace std;
typedef long long LL;
const int maxn = 1e5 + 10;
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define pb push_back
map<string,int>f1;
map<int,string>f2;
std::vector<int>G[maxn];
map<pair<int,int>,int>ans;
std::vector<int>query[maxn];
int ql[maxn],qr[maxn];
int col[maxn],p[maxn];
int findx(int x){
return p[x]==x? x:p[x]=findx(p[x]);
}
void Union(int u,int v){
p[findx(v)]=findx(u);
}
void Init(int n){
for(int i=0;i<=n;i++){
query[i].clear();
G[i].clear();
col[i]=0;
p[i]=i;
}
f1.clear();
f2.clear();
ans.clear();
}
void lca(int u){
for(int i=0;i<G[u].size();i++){
lca(G[u][i]);
Union(u,G[u][i]);
}
col[u]=1;
for(int i=0;i<query[u].size();++i){
int v=query[u][i];
if(col[v]){
ans[make_pair(u,v)]=findx(v);
}
}
}
int main(){
ios_base::sync_with_stdio(false);
cin.tie(0);
int n,m;
while(cin>>n){
string fa,son;
int tot=0;
Init(n+3);
for(int i=1;i<=n;i++){
cin>>fa>>son;
if(!f1[fa]){
f1[fa]=++tot;
f2[tot]=fa;
}if(!f1[son]){
f1[son]=++tot;
f2[tot]=son;
}
//cout<<f1[fa]<<' '<<f1[son]<<endl;
G[f1[fa]].pb(f1[son]);
}
cin>>m;
for(int i=0;i<m;i++){
cin>>fa>>son;
ql[i]=f1[fa];
qr[i]=f1[son];
query[ql[i]].pb(qr[i]);
query[qr[i]].pb(ql[i]);
}
lca(1);
for(int i=0;i<m;i++){
int x=0;
x=ans[make_pair(ql[i],qr[i])];
if(!x)x=ans[make_pair(qr[i],ql[i])];
cout<<f2[x]<<endl;
}
}
return 0;
}

离线LCA学习的更多相关文章

  1. HDU 5044 离线LCA算法

    昨天写了HDU 3966 ,本来这道题是很好解得,结果我想用离线LCA 耍一把,结果发现离线LCA 没理解透,错了好多遍,终得AC ,这题比起 HDU 3966要简单,因为他不用动态查询.但是我还是错 ...

  2. 【图论】tarjan的离线LCA算法

    百度百科 Definition&Solution 对于求树上\(u\)和\(v\)两点的LCA,使用在线倍增可以做到\(O(nlogn)\)的复杂度.在NOIP这种毒瘤卡常比赛中,为了代码的效 ...

  3. HDU 2586 How far away ? 离线lca模板题

    How far away ? Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)To ...

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

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

  5. poj1470 Closest Common Ancestors [ 离线LCA tarjan ]

    传送门 Closest Common Ancestors Time Limit: 2000MS   Memory Limit: 10000K Total Submissions: 14915   Ac ...

  6. SPOJ 10628 Count on a tree(Tarjan离线LCA+主席树求树上第K小)

    COT - Count on a tree #tree You are given a tree with N nodes.The tree nodes are numbered from 1 to  ...

  7. POJ-1330--Nearest Common Ancestors(离线LCA)

    LCA离线算法 它需要一次输入所有的询问,然后有根节点开始进行深度优先遍历(DFS),在深度优先遍历的过程中,进行并查集的操作,同时查询询问,返回结果. 题意: 求A ,B两点的最近公共祖先 分析: ...

  8. 关于Tarjan(3)——离线LCA

    LCA(最近公共祖先),指对于一棵树上任意两个节点往上走最早都能到达的节点. 求LCA有两种方法,一种是倍增,另一种则是Tarjan........ Tarjan巧妙利用并查集的思想: 这里的Tarj ...

  9. HDU 2586.How far away ?-离线LCA(Tarjan)

    2586.How far away ? 这个题以前写过在线LCA(ST)的,HDU2586.How far away ?-在线LCA(ST) 现在贴一个离线Tarjan版的 代码: //A-HDU25 ...

随机推荐

  1. php开发之命名规则

    类命名 1.使用大写的字母作为词的切割,其它字母均使用小写字母 2.名字的首字母使用大写字母 3.不要使用下划线"_" 类属性的命名 1.属性的命名应该以'm'为前缀 2.前缀'm ...

  2. Revit Family API 添加对齐

    没测试成功,留待以后研究. [TransactionAttribute(Autodesk.Revit.Attributes.TransactionMode.Manual)] ; ; i < nV ...

  3. CTreeCtrl和CListCtrl失去焦点时高亮选中项

    设置CTreeCtrl的Always Show Selection:TrueCListCtrl的Always Show Selection:False在NM_CUSTOMDRAW事件中添加如下代码: ...

  4. 用C扩展Python2

    参考 python扩展实现方法--python与c混和编程 编写Python扩展(Extending Python with C or C++) https://docs.python.org/2.7 ...

  5. GIS中的数据库.gdb与.mdb的区别

    gdb是文件地理数据库,mdb是个人地理数据库,都是数据库文件类型. 个人地理数据库,是以access数据库为基础的个人将数据库格式mdb,可以存储不超过2G的文件,只适合Windows系统下: 文件 ...

  6. uitextfield 设置为密码框显示

    uitextfield 设置为密码框显示: 在xib中,将文本secure的复选框选中即可.

  7. Windows下安装WebLogic

    WebLogic安装结束 以下是进入MyEclipse启动配置WebLogic

  8. 好用的批量改名工具——文件批量改名工具V2.0 绿色版

    我找了一个绿色免安装的软件来实现批量改名要求 下载地址:http://www.orsoon.com/Soft/14049.html#xiazai 添加图片后,开始改名.通过输入a#就可以将这些图片进行 ...

  9. RocketMQ logback使用实践

    logback_broker.xml <?xml version="1.0" encoding="UTF-8"?> <!-- Licensed ...

  10. dubbo源码解析-spi(4)

    前言 本篇是spi的第四篇,本篇讲解的是spi中增加的AOP,还是和上一篇一样,我们先从大家熟悉的spring引出AOP. AOP是老生常谈的话题了,思想都不会是一蹴而就的.比如架构设计从All in ...