【HIHOCODER 1067】最近公共祖先·二(LCA)
描述
上上回说到,小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<=105,M<=105, 且数据中所有涉及的人物中不存在两个名字相同的人(即姓名唯一的确定了一个人),所有询问中出现过的名字均在之前所描述的N对父子关系中出现过,第一个出现的名字所确定的人是其他所有人的公共祖先。
输出
对于每组测试数据,对于每个小Hi的询问,按照在输入中出现的顺序,各输出一行,表示查询的结果:他们的所有共同祖先中辈分最低的一个人的名字。
样例输入
4
Adam Sam
Sam Joey
Sam Micheal
Adam Kevin
3
Sam Sam
Adam Sam
Micheal Kevin
样例输出
Sam
Adam
Adam
题解
题解:http://hihocoder.com/problemset/problem/1067
#include <map>
#include <cmath>
#include <cstdio>
#include <complex>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#define ll long long
#define inf 0
#define PI acos(-1)
#define bug puts("here")
#define REP(i,x,n) for(int i=x;i<=n;i++)
#define DEP(i,n,x) for(int i=n;i>=x;i--)
#define mem(a,x) memset(a,x,sizeof(a))
typedef unsigned long long ull;
using namespace std;
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
inline void Out(int a){
if(a<0) putchar('-'),a=-a;
if(a>=10) Out(a/10);
putchar(a%10+'0');
}
const int MOD=1000000007;
const int N=100000+5;
int fa[N],head[N],head2[N],tot,tot2;
bool in[N];
map<int,int>vis2;
int n,m;
struct node{
int to,nex,id;
node(int u,int v,int ti=0):to(u),nex(v),id(ti){}
node(){}
}Path[N<<1],query[N<<1];
void Addedge(int u,int v){
Path[++tot]=node(v,head[u]);
head[u]=tot;
}
void Addedge2(int u,int v,int id){
query[++tot2]=node(v,head2[u],id);
head2[u]=tot2;
}
int hashstr(char* str){
int res=0;
REP(i,0,strlen(str)-1){
res=(res*233+str[i])%MOD;
}
return res;
}
int find(int x){return fa[x]==-1?x:fa[x]=find(fa[x]);}
bool vis[N];
int ancestor[N],ans[N];
char name[N][20];
void lca(int u){
vis[u]=true;
ancestor[u]=u;
for(int i=head[u];i;i=Path[i].nex){
int v=Path[i].to;
if(vis[v]) continue;
lca(v);
int f1=find(u),f2=find(v);
if(f1!=f2) fa[f2]=f1;
ancestor[find(u)]=u;
}
for(int i=head2[u];i;i=query[i].nex){
int v=query[i].to;
if(vis[v]){
ans[query[i].id]=ancestor[find(v)];
}
}
}
int main(){
n=read();
char s1[20],s2[20];
memset(head,-1,sizeof(head));
memset(head2,-1,sizeof(head2));
memset(fa,-1,sizeof(fa));
int cnt=0;
REP(i,1,n){
scanf("%s%s",s1,s2);
int ha1=hashstr(s1);
int ha2=hashstr(s2);
if(!vis2[ha1])
vis2[ha1]=++cnt,strcpy(name[cnt],s1);
if(!vis2[ha2])
vis2[ha2]=++cnt,strcpy(name[cnt],s2);
ha1=vis2[ha1];ha2=vis2[ha2];
Addedge(ha1,ha2);
Addedge(ha2,ha1);
in[ha2]=true;
}
m=read();
REP(i,1,m){
scanf("%s%s",s1,s2);
int ha1=hashstr(s1);
int ha2=hashstr(s2);
ha1=vis2[ha1];ha2=vis2[ha2];
Addedge2(ha1,ha2,i);
Addedge2(ha2,ha1,i);
}
int root=1;
REP(i,1,n){
if(!in[i])root=i;
}
lca(root);
REP(i,1,m){
printf("%s\n",name[ans[i]]);
}
return 0;
}
【HIHOCODER 1067】最近公共祖先·二(LCA)的更多相关文章
- hihoCoder #1067 : 最近公共祖先·二 [ 离线LCA tarjan ]
传送门: #1067 : 最近公共祖先·二 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 上上回说到,小Hi和小Ho用非常拙劣——或者说粗糙的手段山寨出了一个神奇的网站 ...
- Hihocoder #1067 : 最近公共祖先·二
时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 上上回说到,小Hi和小Ho用非常拙劣——或者说粗糙的手段山寨出了一个神奇的网站,这个网站可以计算出某两个人的所有共同祖先中 ...
- HihoCoder 1067 最近公共祖先(ST离线算法)
最近公共祖先·二 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 上上回说到,小Hi和小Ho用非常拙劣——或者说粗糙的手段山寨出了一个神奇的网站,这个网站可以计算出某两个 ...
- hihoCoder week15 最近公共祖先·二
tarjan求lca 就是dfs序中用并查集维护下,当访问到询问的第二个点u的时候 lca就是第一点的find(fa[v]) fa[v] = u; // 当v为u的儿子 且 v已经dfs完毕 #i ...
- hihoCoder week17 最近公共祖先·三 lca st表
记录dfs序列,dfn[tot] 记录第tot次访问的节点 然后查两点在dfs序中出现的第一次 id[u] id[v] 然后 找 dep[k] = min( dep[i] ) {i 属于 [id[u ...
- hihocoder1067 最近公共祖先·二(tarjin算法)(并查集)
#1067 : 最近公共祖先·二 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 上上回说到,小Hi和小Ho用非常拙劣——或者说粗糙的手段山寨出了一个神奇的网站,这个网站 ...
- 最近公共祖先问题 LCA
2018-03-10 18:04:55 在图论和计算机科学中,最近公共祖先,LCA(Lowest Common Ancestor)是指在一个树或者有向无环图中同时拥有v和w作为后代的最深的节点. 计算 ...
- 「LuoguP3379」 【模板】最近公共祖先(LCA)
题目描述 如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 输入输出格式 输入格式: 第一行包含三个正整数N.M.S,分别表示树的结点个数.询问的个数和树根结点的序号. 接下来N-1行每 ...
- 洛谷P3379 【模板】最近公共祖先(LCA)
P3379 [模板]最近公共祖先(LCA) 152通过 532提交 题目提供者HansBug 标签 难度普及+/提高 提交 讨论 题解 最新讨论 为什么还是超时.... 倍增怎么70!!题解好像有 ...
- 最近公共祖先:LCA及其用倍增实现 +POJ1986
Q:为什么我在有些地方看到的是最小公共祖先? A:最小公共祖先是LCA(Least Common Ancestor)的英文直译,最小公共祖先与最近公共祖先只是叫法不同. Q:什么是最近公共祖先(LCA ...
随机推荐
- Glide加载图片的事例
//获取图片的url String url = resultsEntity.getUrl(); //判断获取的图片是否存在 if (resultsEntity.getItemHeight() > ...
- The Weakest Sith
http://codeforces.com/gym/101149/problem/F 题目要输出最丑陋的衣服.所以每件衣服都要和其他衣服比一次. 但是注意到,能赢一件衣服的衣服,就算是好衣服了. 那么 ...
- 如何查找Oracle某列值相同的字段
相关的sql语句如下 select xm_guidfrom T_NZYDKgroup by xm_guidhaving count (*)>1
- asp.net excel导出红色字体
文章转自网上的一位朋友,非常感谢! 后台代码 public void ExportDataTableToExcel(System.Data.DataTable s_DataTable) { int t ...
- 声明已被否决 VS C++
error C4996声明已被否决,不止一次碰到这个问题,在这里必须mark一下! 尝试这个1.Project Properties > Configuration Properties > ...
- 分布式定时任务的redis锁实现
一个web项目如果部署为分布式时,平时常见的定时服务在一定的间隔时间内,可能出现多次重复调用的问题.而此时由于是不同容器之间的竞争,因此需要容器级别的锁 Redis为单进程单线程模式,采用队列模式将并 ...
- HTML iframe框架
iframe 作用: 就是在一个网页插入一个小窗口 窗口里面也是一个网页 <a href="http://www.baidu.com" target="da1& ...
- Gym - 101291C (很有意思的最短路)
题意: 给出一张地图和机器人还有出口的位置,地图上面有障碍.然后给出UDLR上下左右四种指令,遇到障碍物或者越界的指令会忽略,剩下的继续执行. 只要到达出口就算找到出口,然后给你一串指令,让你修改指令 ...
- python matplotlib 可视化操作实例
具体代码: # encoding: utf-8 # coding = utf-8 import sys reload(sys) sys.setdefaultencoding('utf8') from ...
- CPP-基础:关于内存分配
1:c中的malloc和c++中的new有什么区别 (1)new.delete 是操作符,可以重载,只能在C++中使用.(2)malloc.free是函数,可以覆盖,C.C++中都可以使用.(3)ne ...