zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    C 语言 静态库和动态库的创建和应用
    C++ 中英文术语对照
    下午
    [转]内核 do_fork 函数源代码浅析
    关于C#反射机制,自己写的
    获取字符串中数字
    关于C#反射机制,来源于网络
    关于 Nhinernate 的one to one(转载)
    鼠标坐标的记录
    关于C#中hibernate.cfg.xml动态加载问题
  • 原文地址:https://www.cnblogs.com/boring09/p/4376732.html
Copyright © 2011-2022 走看看