之前就写的是离线算法。思路就是先序一遍树,记录层数,然后高效RMQ就好。ST和线段树都能过。

以后有时间将之前的在线算法补上。

#include <bits/stdc++.h>

using namespace std;

#define MAXN 100005
#define MAXM 105
#define inf 0x7ffffff
int n;
struct Edge {
int v, next;
} edge[MAXN];
int head[MAXN];
int e; void addEdge(int u, int v) { //加边
edge[e].v = v;
edge[e].next = head[u];
head[u] = e++;
}
int first[MAXN];//结点在搜索顺序数组中最先出现的位置(下标)
int occur[MAXN << ]; //结点在出现的顺序数组重复的也要记录
int depth[MAXN << ]; //结点在搜索树中的深度,与occur相对应
int dp_min[MAXN << ][]; //dp_min[i][j] 表示从第i个位置开始的2^j个元素中的最小值的下标
int m = ; //不断记录出现的下标 void dfs(int u, int deep) {
occur[++m] = u; //进入该点时进行记录
depth[m] = deep;
if(!first[u])
first[u] = m;
for(int i = head[u]; i + ; i = edge[i].next) {
dfs(edge[i].v, deep + );
occur[++m] = u; //访问子树返回也要标记
depth[m] = deep;
}
}
void init() {
memset(head, -, sizeof(head));
e = ;
} void RMQ_init(int num) {
for(int i = ; i <= num; i++)
dp_min[i][] = i; //注意dp_min存的不是最小值,而是最小值的下标
for(int j = ; j < ; j++)
for(int i = ; i <= num; i++) {
if(i + ( << j) - <= num) {
dp_min[i][j] = depth[dp_min[i][j - ]] < depth[dp_min[i + ( << (j - ))][j - ]] ? dp_min[i][j - ] : dp_min[i + ( << (j - ))][j - ];
}
}
} int RMQ_min(int a, int b) {
int l = first[a], r = first[b]; //得到区间左右端点
if(l > r) {
int t = l;
l = r;
r = t;
}
int k = (int)(log(double(r - l + )) / log(2.0));
int min_id = depth[dp_min[l][k]] < depth[dp_min[r - ( << k) + ][k]] ? dp_min[l][k] : dp_min[r - ( << k) + ][k]; //最小值下标
return occur[min_id];//取得当前下标表示的结点
} map<string, int> Hash_zh;
map<int, string> Hash_fa; int main() {
int t, a, b;
init();
m = ;
memset(first, , sizeof(first));
bool in[MAXN];//记录结点有无入度
memset(in, false, sizeof(in));
int u = , v = , cnt = ;
string str_u, str_v;
scanf("%d", &n);
for(int i = ; i <= n; i++) { //注意此题只有n-1条边
cin >> str_u >> str_v;
if (Hash_zh[str_u] == ) {
Hash_fa[cnt] = str_u;
Hash_zh[str_u] = cnt ++;
}
if (Hash_zh[str_v] == ) {
Hash_fa[cnt] = str_v;
Hash_zh[str_v] = cnt ++;
}
u = Hash_zh[str_u];
v = Hash_zh[str_v];
addEdge(u, v); //u->v单向
//in[v] = true;
}
dfs(, );
RMQ_init(m);
int op_n;
scanf ("%d", &op_n);
while (op_n --) {
cin >> str_u >> str_v;
if (str_u == str_v) {
cout << str_u << endl;
continue;
}
u = Hash_zh[str_u];
v = Hash_zh[str_v];
cout << Hash_fa[RMQ_min(u, v)] << endl;
} return ;
}

【hihoCoder第十七周】最近公共祖先·三的更多相关文章

  1. hihocoder1069 最近公共祖先·三(tarjin算法)(并查集)

    #1069 : 最近公共祖先·三 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 上上回说到,小Hi和小Ho使用了Tarjan算法来优化了他们的“最近公共祖先”网站,但是 ...

  2. 最近公共祖先-三(RMQ-ST)

    描述 上上回说到,小Hi和小Ho使用了Tarjan算法来优化了他们的"最近公共祖先"网站,但是很快这样一个离线算法就出现了问题:如果只有一个人提出了询问,那么小Hi和小Ho很难决定 ...

  3. hihoCoder week17 最近公共祖先·三 lca st表

    记录dfs序列,dfn[tot] 记录第tot次访问的节点 然后查两点在dfs序中出现的第一次 id[u] id[v] 然后  找 dep[k] = min( dep[i] ) {i 属于 [id[u ...

  4. hihoCoder#1069 最近公共祖先·三

    原题地址 根据提示用Spase Table做 将Tree先展成List,因为数组长度等于边数的2倍,树中边数等于节点数-1,所以List数组只要开2倍节点数大小即可 WA了几次,原来是查询的时候出现左 ...

  5. HihoCoder第十三周:最近公共祖先 一

    #1062 : 最近公共祖先·一 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 同城那样神奇,但这个网站仍然让小Ho乐在其中,但这是为什么呢? "为什么呢?& ...

  6. Solution: 最近公共祖先·一 [hiho一下 第十三周]

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

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

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

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

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

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

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

随机推荐

  1. iOS之UITableView带滑动操作菜单的Cell

    制作一个可以滑动操作的 Table View Cell 本文翻译自 http://www.raywenderlich.com/62435/make-swipeable-table-view-cell- ...

  2. (转)基于企业级证书的IOS应用打包升级功能介绍

    IOS应用程序升级流程介绍:IOS手机端应用程序需要升级时,打开服务器端html文件(本文为ucab.html文件)->点击在线安装->打开plist文件(本文中为ucab.plist文件 ...

  3. [转]ANDROID仿IOS微信滑动删除_SWIPELISTVIEW左滑删除例子

    转载:http://dwtedx.sinaapp.com/itshare_290.html 本例子实现了滑动删除ListView的Itemdemo的效果.大家都知道.这种创意是来源于IOS的.左滑删除 ...

  4. [ES6] Objects create-shorthand && Destructuring

    Creating Object: Example 1: let name = "Brook"; let totalReplies = 249; let avatar = " ...

  5. TypedArray和obtainStyledAttributes使用

    在编写Android自定义按钮示例基础上,如果要指定字体大小产生这样的效果: 其实是不需要自定义变量的,可以直接使用TextView的配置属性: <com.easymorse.textbutto ...

  6. Activity具体解释(生命周期、以各种方式启动Activity、状态保存,全然退出等)

    一.什么是Activity? 简单的说:Activity就是布满整个窗体或者悬浮于其它窗体上的交互界面.在一个应用程序中通常由多个Activity构成,都会在Manifest.xml中指定一个主的Ac ...

  7. Win2 Socket(套接字)相关 API

    Socket(套接字) 作者信息 肖进 单位:南京中萃食品有限公司 资讯部 邮箱:xiaoj@njb.swirebev.com 电话:025-58642091 与socket有关的一些函数介绍 1.读 ...

  8. Win8 弹出窗口不在最前端的解决方法

    Win8系统的使用者有很多会遇到弹出窗口不在最前端的情况(自动隐藏,点下页面又出来),比如另存为的时候 ,或是登录路由器时弹出的登录框时. 引起这个异常的原因是与系统输入法冲突引起,但又不可能不用第三 ...

  9. Javascript高级程序设计读书笔记(第10章 DOM)

    第10章 DOM 10.1  节点层次 每个节点都有一个nodeType属性,用于表明节点的类型.任何节点类型必是下面中的一个: Node.Element_NODE(1); NODE.ATTRIBUT ...

  10. Redhat修改本地yum源

    1.将Centos系统的ios文件传到服务器,比如传到/root目录下: 2.将ios文件挂载到本地,需要在本地建立一个文件夹,比如/yum; mkdir /yum mount -o loop /ro ...