hihoCoder#1067 最近公共祖先·二

原题地址

超时、超内存都碰到了。。最后还是参考了这篇博文才勉强AC

需要注意:

1. 肯定是树而不是森林,而且树的根节点一定是第一个出现的名字,所以不需要再去找哪个是根了。这样可以节省一部分内存。

2. 用并查集路径压缩的方法维护并查集结构即可,当查找的时候再压缩,不需要每次染黑节点的时候都压缩。这样可以节省一部分时间。

3. 字符串都转成id再做。

4. 能静态申请内存就尽量用静态内存,比如数组,STL少用,尤其是map,效率极低。

代码:

 1 #include <iostream>
 2 #include <map>
 3 #include <set>
 4 #include <vector>
 5 #include <cstring>
 6
 7 using namespace std;
 8
 9 #define SIZE 100010
10
11 int N, M;
12 vector<int> tree[SIZE];
13 int color[SIZE];
14 int ancestor[SIZE];
15 vector<pair<int, int> > query[SIZE];
16 int ans[SIZE];
17 map<string, int> a2i;
18 string i2a[SIZE];
19
20 int find_gray(int node) {
21   if (color[node] == 1)
22     return node;
23   int gray = find_gray(ancestor[node]);
24   ancestor[node] = gray;
25   return gray;
26 }
27
28 void traverse(int root) {
29   color[root] = 1;
30   for (auto q : query[root]) {
31     if (ans[q.second] != 0)
32       continue;
33     if (color[q.first] == 1)
34       ans[q.second] = q.first;
35     if (color[q.first] == 2)
36       ans[q.second] = find_gray(q.first);
37   }
38
39   for (auto c : tree[root])
40     traverse(c);
41
42   color[root] = 2;
43 }
44
45 int main() {
46   memset(color, 0, SIZE * sizeof(int));
47   memset(ancestor, 0, SIZE * sizeof(int));
48   memset(ans, 0, SIZE * sizeof(int));
49
50   int order = 1;
51   cin >> N;
52   for (int i = 0; i < N; i++) {
53     string f, s;
54     int fi, si;
55     cin >> f >> s;
56     fi = a2i[f];
57     si = a2i[s];
58     if (fi == 0) {
59       fi = a2i[f] = order;
60       i2a[order] = f;
61       order++;
62     }
63     if (si == 0) {
64       si = a2i[s] = order;
65       i2a[order] = s;
66       order++;
67     }
68     tree[fi].push_back(si);
69     ancestor[si] = fi;
70     color[fi] = color[si] = 0;
71   }
72   cin >> M;
73   for (int i = 0; i < M; i++) {
74     string a, b;
75     int ai, bi;
76     cin >> a >> b;
77     ai = a2i[a];
78     bi = a2i[b];
79     query[ai].push_back(pair<int, int>(bi, i));
80     query[bi].push_back(pair<int, int>(ai, i));
81   }
82
83   traverse(1);
84
85   for (int i = 0; i < M; i++)
86     cout << i2a[ans[i]] << endl;
87
88   return 0;
89 }
时间: 2024-12-22 21:01:53

hihoCoder#1067 最近公共祖先·二的相关文章

hihoCoder #1067 : 最近公共祖先&#183;二 [ 离线LCA tarjan ]

传送门: #1067 : 最近公共祖先·二 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 上上回说到,小Hi和小Ho用非常拙劣——或者说粗糙的手段山寨出了一个神奇的网站,这个网站可以计算出某两个人的所有共同祖先中辈分最低的一个是谁.远在美国的他们利用了一些奇妙的技术获得了国内许多人的相关信息,并且搭建了一个小小的网站来应付来自四面八方的请求. 但正如我们所能想象到的……这样一个简单的算法并不能支撑住非常大的访问量,所以摆在小Hi和小Ho面前的无非两种选择: 其一是

hihocoder 1067 最近公共祖先&#183;二 并查集+stl

题目链接: hihocoder1067 题解思路: 面对10^5个 名字和10^5条询问,肯定要用到特殊的方法: 1.把所有的询问先存下来,然后再遍历一次整棵树得到所有答案 2.遍历的过程中   查询含当前节点的 所有询问,然后找到询问中的另一个节点:查看另一个节点的状态. 如果另一个节点未访问过,接下来处理: 如果另一个节点正在被访问(子节点未访问完),则答案就是这个节点 如果另一个节点已被访问过,则答案是它的正在被访问的根节点 3. 第二点的状态需要并查集处理 未遍历时所有节点标记为未访问

hihoCoder_#1067_最近公共祖先&#183;二(LCA模板)

#1067 : 最近公共祖先·二 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 上上回说到,小Hi和小Ho用非常拙劣--或者说粗糙的手段山寨出了一个神奇的网站,这个网站可以计算出某两个人的所有共同祖先中辈分最低的一个是谁.远在美国的他们利用了一些奇妙的技术获得了国内许多人的相关信息,并且搭建了一个小小的网站来应付来自四面八方的请求. 但正如我们所能想象到的--这样一个简单的算法并不能支撑住非常大的访问量,所以摆在小Hi和小Ho面前的无非两种选择: 其一是购买更为昂

hicocoder1067 最近公共祖先&#183;二(tarjan算法)

tarjan算法是处理最近公共祖先问题的一种离线算法. 算法思路: 先将所有的询问搜集起来. 然后对树进行dfs,在dfs的过程中对节点进行着色.当到达某个节点x的时候,给x着色为灰色,离开x的时候,着色为黑色. 当到达x并将其着色为灰色后,处理与x相关联的所有询问: (这里有一个显然的事实:所有的灰色节点都是x的祖先) (1)若询问的另一个节点y是灰色,那么该询问的结果为y: (2)若询问的另一个节点y是黑色,那么询问结果应为离y最近的y的灰色祖先(因为所有灰色节点都是x的祖先,所以离y最近的

hiho一下 第十五周——最近公共祖先&#183;二(Trajan,离线LCA)

题目连接 http://hihocoder.com/problemset/problem/1067 题目大意 就是一棵树求任意两个节点的最近公共祖先. 算法描述 在题目的提示里面有比较详细的解释.这里就不多说了.这种算法的时间复杂度是O(n+q). 在算法的实现上也有一些技巧,在参考了一些代码后写了一个比较精简的Trajan_LAC算法. #include <bits/stdc++.h> using namespace std; typedef long long LL; const int

[ACM] hihocoder 1062 最近公共祖先&#183;一 (一般做法)

描述 小Ho最近发现了一个神奇的网站!虽然还不够像58同城那样神奇,但这个网站仍然让小Ho乐在其中,但这是为什么呢? "为什么呢?"小Hi如是问道,在他的观察中小Ho已经沉迷这个网站一周之久了,甚至连他心爱的树玩具都弃置一边. "嘿嘿,小Hi,你快过来看!"小Ho招呼道. "你看,在这个对话框里输入我的名字,在另一个对话框里,输入你的名字,再点这个查询按钮,就可以查出来--什么!我们居然有同一个祖祖祖祖祖爷爷?" "诶,真是诶--这个网

[hiho 15]最近公共祖先 二

题目描述 这次使用离线算法来解决最近公共祖先的问题. 离线算法可以一遍 dfs 处理完所有的查询,因而需要把查询全部储存起来. 具体的 dfs 过程是: 所有节点最初标记为白色,第一次经过该节点时,将其染成灰色,第二次经过该节点时(即离开该节点时)将其染成黑色. 在 dfs 的某个状态下,白色代表未访问的节点,黑色代表已经访问完该节点为根整个子树,灰色代表正在访问该节点为根的子树. 可以在每个节点处查询与该节点相关的所有查询,每个查询对应有另一个节点X(可能是自身): 如果X是白色,说明还未访问

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

#1062 : 最近公共祖先·一 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Ho最近发现了一个神奇的网站!虽然还不够像58同城那样神奇,但这个网站仍然让小Ho乐在其中,但这是为什么呢? “为什么呢?”小Hi如是问道,在他的观察中小Ho已经沉迷这个网站一周之久了,甚至连他心爱的树玩具都弃置一边. “嘿嘿,小Hi,你快过来看!”小Ho招呼道. “你看,在这个对话框里输入我的名字,在另一个对话框里,输入你的名字,再点这个查询按钮,就可以查出来……什么!我们居然有同

hihoCoder 1062 最近公共祖先&#183;一 最详细的解题报告

题目来源:最近公共祖先·一 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 题目描述 小Ho最近发现了一个神奇的网站!虽然还不够像58同城那样神奇,但这个网站仍然让小Ho乐在其中,但这是为什么呢? “为什么呢?”小Hi如是问道,在他的观察中小Ho已经沉迷这个网站一周之久了,甚至连他心爱的树玩具都弃置一边. “嘿嘿,小Hi,你快过来看!”小Ho招呼道. “你看,在这个对话框里输入我的名字,在另一个对话框里,输入你的名字,再点这个查询按钮,就可以查出来……什么!我们居然有同一