【hihoCoder第十七周】最近公共祖先·三
之前就写的是离线算法。思路就是先序一遍树,记录层数,然后高效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第十七周】最近公共祖先·三的更多相关文章
- hihocoder1069 最近公共祖先·三(tarjin算法)(并查集)
#1069 : 最近公共祖先·三 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 上上回说到,小Hi和小Ho使用了Tarjan算法来优化了他们的“最近公共祖先”网站,但是 ...
- 最近公共祖先-三(RMQ-ST)
描述 上上回说到,小Hi和小Ho使用了Tarjan算法来优化了他们的"最近公共祖先"网站,但是很快这样一个离线算法就出现了问题:如果只有一个人提出了询问,那么小Hi和小Ho很难决定 ...
- hihoCoder week17 最近公共祖先·三 lca st表
记录dfs序列,dfn[tot] 记录第tot次访问的节点 然后查两点在dfs序中出现的第一次 id[u] id[v] 然后 找 dep[k] = min( dep[i] ) {i 属于 [id[u ...
- hihoCoder#1069 最近公共祖先·三
原题地址 根据提示用Spase Table做 将Tree先展成List,因为数组长度等于边数的2倍,树中边数等于节点数-1,所以List数组只要开2倍节点数大小即可 WA了几次,原来是查询的时候出现左 ...
- HihoCoder第十三周:最近公共祖先 一
#1062 : 最近公共祖先·一 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 同城那样神奇,但这个网站仍然让小Ho乐在其中,但这是为什么呢? "为什么呢?& ...
- Solution: 最近公共祖先·一 [hiho一下 第十三周]
题目1 : 最近公共祖先·一 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Ho最近发现了一个神奇的网站!虽然还不够像58同城那样神奇,但这个网站仍然让小Ho乐在其中 ...
- hihocoder #1062 : 最近公共祖先·一(小数据量 map+set模拟+标记检查 *【模板】思路 )
#1062 : 最近公共祖先·一 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Ho最近发现了一个神奇的网站!虽然还不够像58同城那样神奇,但这个网站仍然让小Ho乐在 ...
- 【HIHOCODER 1067】最近公共祖先·二(LCA)
描述 上上回说到,小Hi和小Ho用非常拙劣--或者说粗糙的手段山寨出了一个神奇的网站,这个网站可以计算出某两个人的所有共同祖先中辈分最低的一个是谁.远在美国的他们利用了一些奇妙的技术获得了国内许多人的 ...
- hihoCoder 1062 最近公共祖先·一 最详细的解题报告
题目来源:最近公共祖先·一 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 题目描述 小Ho最近发现了一个神奇的网站!虽然还不够像58同城那样神奇,但这个网站仍然让小Ho乐在其 ...
随机推荐
- javaweb笔记1之入门
1 web应用的目录结构 web的根目录自定义 其中可以包括静态资源(html,image,css,js) |-WEB-INF(注意格式就是这样,大小写等等一模一样) |-class:存放的是字节码文 ...
- android .9.png ”点九” 图片制作方法
“点九”是andriod平台的应用软件开发里的一种特殊的图片形式,文件扩展名为:.9.png 智能手机中有自动横屏的功能,同一幅界面会在随着手机(或平板电脑)中的方向传感器的参数不同而改变显示的方向, ...
- [Angular 2] Simple intro Http
To use http, we need to import the HTTP_PROVIDER, so that we can inject http to other component: imp ...
- Android(java)学习笔记260:JNI之native方法头文件的生成
1. JDK1.6 ,进入到工程的bin目录下classes目录下: 使用命令: javah packageName.ClassName 会在当前目录下生成头文件,从头文件找到jni协议方法 下面举 ...
- DataGrid( 数据表格) 组件[9]
本节课重点了解 EasyUI 中 DataGrid(数据表格)组件的使用方法,这个组件依赖于Panel(面板).Resizeable(调整大小).LinkButton(按钮).Pageination( ...
- linux 使用ptrace函数时找不到头文件 .h 或者找不到某个宏的解决方法
例如: #include <stdio.h> #include <sys/ptrace.h> #include <sys/types.h> #include < ...
- C#类中字段,属性与方法
person类 using System; using System.Collections.Generic; using System.Linq; using System.Text; using ...
- uva 1595 - Symmetry
思路:首先,如果这些点对称,那么它们的对称轴是x = m(m是所有点横坐标的平均值): 把这些点放到一个集合里,然后扫描每个点,计算出它关于x = m的对称点,看这个点是否在集合里面. 如果有 ...
- 12个用得着的JQuery代码片段
1. 导航菜单背景切换效果 在项目的前端页面里,相对于其它的导航菜单,激活的导航菜单需要设置不同的背景.这种效果实现的方式有很多种,下面是使用JQuery实现的一种方式: <ul id='nav ...
- 转载:对#!/bin/sh的认识
转载网址:http://blog.163.com/hashes@yeah/blog/static/16867631220101029847420/ 对#!/bin/sh的认识 第一次学shell编程, ...