HihoCoder 1067 最近公共祖先(ST离线算法)
最近公共祖先·二
描述
上上回说到,小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算法;
在线:ST算法;
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<map>
using namespace std;
const int maxn=;
int tot,ver[maxn],dept[maxn],first[maxn];
int cnt,Laxt[maxn],Next[maxn],To[maxn],vis[maxn];
int dp[maxn][];
int personnum,m;//人数,问题数
map<string,int>q;//q和name相对
map<int,string>name; void add(int u,int v)
{
Next[++cnt]=Laxt[u];
Laxt[u]=cnt;
To[cnt]=v;
} void dfs(int u ,int dep)
{
vis[u]=true;
ver[++tot] = u;
first[u] = tot;
dept[tot] = dep;
for(int i=Laxt[u];i;i=Next[i])
if( !vis[To[i]] )
{
dfs(To[i],dep+);
ver[++tot] = u;
dept[tot] = dep;
}
} void ST(int n)
{
for(int i=;i<=n;i++) dp[i][] = i;
for(int j=;(<<j)<=n;j++)
{
for(int i=;i+(<<j)-<=n;i++)
{
int a = dp[i][j-] , b = dp[i+(<<(j-))][j-];
dp[i][j] = dept[a]<dept[b]?a:b;
}
}
} int RMQ(int l,int r)
{
int k=;
while((<<(k+))<=r-l+) k++;
int a=dp[l][k],b=dp[r-(<<k)+][k];
return dept[a]<dept[b]?a:b;
} int LCA(int u ,int v)
{
int x = first[u] , y = first[v];
if(x > y) swap(x,y);
int res = RMQ(x,y);
return ver[res];
} int init()
{
int n,i;
string s1,s2,Fa_all;
scanf("%d",&n);
for(i=;i<=n;i++){ cin>>s1>>s2;
if(i==) Fa_all=s1; if(!q[s1]) q[s1]=++personnum;
if(!q[s2]) q[s2]=++personnum;
name[q[s1]]=s1;
name[q[s2]]=s2; add(q[s1],q[s2]);
}
dfs(q[Fa_all],); //搜索
ST(tot);//dp
} int main()
{
init();
string s1,s2;
scanf("%d",&m);//问题 for(int i=;i<=m;i++){
cin>>s1>>s2;
int u=q[s1];
int v=q[s2];
cout<<name[LCA(u,v)]<<endl;
}
return ;
}
HihoCoder 1067 最近公共祖先(ST离线算法)的更多相关文章
- hihoCoder #1067 : 最近公共祖先·二 [ 离线LCA tarjan ]
传送门: #1067 : 最近公共祖先·二 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 上上回说到,小Hi和小Ho用非常拙劣——或者说粗糙的手段山寨出了一个神奇的网站 ...
- LCA 最近公共祖先 Tarjan(离线)算法的基本思路及其算法实现
首先是最近公共祖先的概念(什么是最近公共祖先?): 在一棵没有环的树上,每个节点肯定有其父亲节点和祖先节点,而最近公共祖先,就是两个节点在这棵树上深度最大的公共的祖先节点. 换句话说,就是两个点在这棵 ...
- LCA(最近公共祖先)离线算法Tarjan+并查集
本文来自:http://www.cnblogs.com/Findxiaoxun/p/3428516.html 写得很好,一看就懂了. 在这里就复制了一份. LCA问题: 给出一棵有根树T,对于任意两个 ...
- Hihocoder #1067 : 最近公共祖先·二
时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 上上回说到,小Hi和小Ho用非常拙劣——或者说粗糙的手段山寨出了一个神奇的网站,这个网站可以计算出某两个人的所有共同祖先中 ...
- LCA最近公共祖先 Tarjan离线算法
学习博客: http://noalgo.info/476.html 讲的很清楚! 对于一颗树,dfs遍历时,先向下遍历,并且用并查集维护当前节点和父节点的集合.这样如果关于当前节点(A)的关联节点( ...
- POJ1986 DistanceQueries 最近公共祖先LCA 离线算法Tarjan
这道题与之前那两道模板题不同的是,路径有了权值,而且边是双向的,root已经给出来了,就是1,(这个地方如果还按之前那样来计算入度是会出错的.数据里会出现多个root...数据地址可以在poj的dis ...
- 最近公共祖先LCA(Tarjan算法)的思考和算法实现
LCA 最近公共祖先 Tarjan(离线)算法的基本思路及其算法实现 小广告:METO CODE 安溪一中信息学在线评测系统(OJ) //由于这是第一篇博客..有点瑕疵...比如我把false写成了f ...
- 最近公共祖先LCA(Tarjan算法)的思考和算法实现——转载自Vendetta Blogs
LCA 最近公共祖先 Tarjan(离线)算法的基本思路及其算法实现 小广告:METO CODE 安溪一中信息学在线评测系统(OJ) //由于这是第一篇博客..有点瑕疵...比如我把false写成了f ...
- P5836 [USACO19DEC]Milk Visits S 从并查集到LCA(最近公共祖先) Tarjan算法 (初级)
为什么以它为例,因为这个最水,LCA唯一黄题. 首先做两道并查集的练习(估计已经忘光了).简单来说并查集就是认爸爸找爸爸的算法.先根据线索理认爸爸,然后查询阶段如果发现他们的爸爸相同,那就是联通一家的 ...
随机推荐
- for 循环与嵌套
循环:反复执行某段代码.循环四要素:初始条件,循环条件,循环体,状态改变 for(初始条件;循环条件;状态改变){ 循环体} 给出初始条件,先判断是否满足循环条件,如果不满足条件则跳过for语句,如果 ...
- Connection.setAutoCommit使用的注意事项
http://blog.csdn.net/xiayimiaokuaile/article/details/6422032 setAutoCommit总的来说就是保持数据的完整性,一个系统的更新操作可能 ...
- poj2996
/*排序函数要写对,优先级:K,Q,R,B,N,P 白色的:如果优先级一样,那么按照行数大的优先,如果行数一样,那么列数小的优先 黑色的:如果优先级一样,那么按照行数小的优先,如果行数一样,那么列数小 ...
- [HEOI2016/TJOI2016]求和(第二类斯特林数)
题目 [HEOI2016/TJOI2016]求和 关于斯特林数与反演的更多姿势\(\Longrightarrow\)点这里 做法 \[\begin{aligned}\\ Ans&=\sum\l ...
- tesseract 3.05 release 编译
tesseract 3.05 release版本的对应配置好的vs2015工程.偷懒必备,毕竟依赖那么多库,环境配置还是要费点事的.https://github.com/peirick/VS2015_ ...
- 如何选择合适的MySQL数据类型
一.MySQL数据类型选择原则 更小的通常更好:一般情况下选择可以正确存储数据的最小数据类型.越小的数据类型通常更快,占用磁盘,内存和CPU缓存更小. 简单就好:简单的数据类型的操作通常需要更少的CP ...
- 20145217《信网络对抗》逆向与BOF基础实践
20145217<信网络对抗>逆向与BOF基础实践 内容: 一.简单机器指令,汇编语言 1.'objdump -d xxx|more'反汇编命令查看机器代码,'cat'显示文件内容,'xx ...
- 将CString写入到本地文件中
void SocketU::WritePacket2File(CString packet_str)//packet_str为待写入的字符串{ CTime time = CTime::GetCurre ...
- MySQLdump增量备份、完全备份与恢复
在数据库表丢失或损坏的情况下,备份你的数据库是很重要的.如果发生系统崩溃,你肯定想能够将你的表尽可能丢失最少的数据恢复到崩溃发生时的状态.场景:每周日执行一次完全备份,每天下午1点执行MySQLdum ...
- Effective C++ 条款04:确定对象被使用前已经先被初始化
规则一 永远在使用对象之前将它初始化 int x = 0; const char* text = "A C-style string"; double d; std:: cin & ...