首页 > 代码库 > 【hihoCoder第十七周】最近公共祖先·三
【hihoCoder第十七周】最近公共祖先·三
之前就写的是离线算法。思路就是先序一遍树,记录层数,然后高效RMQ就好。ST和线段树都能过。
以后有时间将之前的在线算法补上。
#include <bits/stdc++.h>using namespace std;#define MAXN 100005#define MAXM 105#define inf 0x7ffffffint 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 << 1]; //结点在出现的顺序数组重复的也要记录int depth[MAXN << 1]; //结点在搜索树中的深度,与occur相对应int dp_min[MAXN << 1][20]; //dp_min[i][j] 表示从第i个位置开始的2^j个元素中的最小值的下标int m = 0; //不断记录出现的下标void dfs(int u, int deep) { occur[++m] = u; //进入该点时进行记录 depth[m] = deep; if(!first[u]) first[u] = m; for(int i = head[u]; i + 1; i = edge[i].next) { dfs(edge[i].v, deep + 1); occur[++m] = u; //访问子树返回也要标记 depth[m] = deep; }}void init() { memset(head, -1, sizeof(head)); e = 0;}void RMQ_init(int num) { for(int i = 1; i <= num; i++) dp_min[i][0] = i; //注意dp_min存的不是最小值,而是最小值的下标 for(int j = 1; j < 20; j++) for(int i = 1; i <= num; i++) { if(i + (1 << j) - 1 <= num) { dp_min[i][j] = depth[dp_min[i][j - 1]] < depth[dp_min[i + (1 << (j - 1))][j - 1]] ? dp_min[i][j - 1] : dp_min[i + (1 << (j - 1))][j - 1]; } }}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 + 1)) / log(2.0)); int min_id = depth[dp_min[l][k]] < depth[dp_min[r - (1 << k) + 1][k]] ? dp_min[l][k] : dp_min[r - (1 << k) + 1][k]; //最小值下标 return occur[min_id];//取得当前下标表示的结点}map<string, int> Hash_zh;map<int, string> Hash_fa;int main() { int t, a, b; init(); m = 0; memset(first, 0, sizeof(first)); bool in[MAXN];//记录结点有无入度 memset(in, false, sizeof(in)); int u = 0, v = 0, cnt = 1; string str_u, str_v; scanf("%d", &n); for(int i = 1; i <= n; i++) { //注意此题只有n-1条边 cin >> str_u >> str_v; if (Hash_zh[str_u] == 0) { Hash_fa[cnt] = str_u; Hash_zh[str_u] = cnt ++; } if (Hash_zh[str_v] == 0) { 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(1, 0); 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 0;}
【hihoCoder第十七周】最近公共祖先·三
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。