zoukankan      html  css  js  c++  java
  • 【hihoCoder第十五周】最近公共祖先·二

    老实说我没有读题,看见标题直接就写了,毕竟hiho上面都是裸的算法演练。

    大概看了下输入输出,套着bin神的模板,做了个正反map映射,但是怎么都得不了满分。等这周结束后,找高人询问下trick。

    若是有人找出了错误,或是发现代码中的不足,求指出。感激!~

    以下是个人80分的代码。(之后献上两天之后的100分代码~_~)。

      1 #include <bits/stdc++.h>
      2 using namespace std;
      3 
      4 const int MAXN = 1000010;
      5 int rmq[2 * MAXN]; //rmq数组,就是欧拉序列对应的深度序列
      6 
      7 struct ST {
      8     int mm[2 * MAXN];
      9     int dp[2 * MAXN][20]; //最小值对应的下标
     10     void init(int n) {
     11         mm[0] = -1;
     12         for(int i = 1; i <= n; i++) {
     13             mm[i] = ((i & (i - 1)) == 0) ? mm[i - 1] + 1 : mm[i - 1];
     14             dp[i][0] = i;
     15         }
     16         for(int j = 1; j <= mm[n]; j++)
     17             for(int i = 1; i + (1 << j) - 1 <= n; i++)
     18                 dp[i][j] = rmq[dp[i][j - 1]] <
     19                            rmq[dp[i + (1 << (j - 1))][j - 1]] ? dp[i][j - 1] : dp[i + (1 << (j - 1))][j - 1];
     20     }
     21     int query(int a, int b) { //查询[a,b]之间最小值的下标
     22         if(a > b)swap(a, b);
     23         int k = mm[b - a + 1];
     24         return rmq[dp[a][k]] <=
     25                rmq[dp[b - (1 << k) + 1][k]] ? dp[a][k] : dp[b - (1 << k) + 1][k];
     26     }
     27 };
     28 //边的结构体定义
     29 struct Edge {
     30     int to, next;
     31 };
     32 
     33 Edge edge[MAXN * 2];
     34 
     35 int tot, head[MAXN];
     36 int F[MAXN * 2]; //欧拉序列,就是dfs遍历的顺序,长度为2*n-1,下标从1开始
     37 int P[MAXN];//P[i]表示点i在F中第一次出现的位置
     38 int cnt;
     39 ST st;
     40 map<string, int> Hash_zh;
     41 map<int, string> Hash_fa;
     42 
     43 void init() {
     44     tot = 0;
     45     memset(head, -1, sizeof(head));
     46     Hash_zh.clear();
     47     Hash_fa.clear();
     48 }
     49 
     50 void addedge(int u, int v) { //加边,无向边需要加两次
     51     edge[tot].to = v;
     52     edge[tot].next = head[u];
     53     head[u] = tot++;
     54 }
     55 
     56 void dfs(int u, int pre, int dep) {
     57     F[++cnt] = u;
     58     rmq[cnt] = dep;
     59     P[u] = cnt;
     60     for(int i = head[u]; i != -1; i = edge[i].next) {
     61         int v = edge[i].to;
     62         if(v == pre)continue;
     63         dfs(v, u, dep + 1);
     64         F[++cnt] = u;
     65         rmq[cnt] = dep;
     66     }
     67 }
     68 void LCA_init(int root, int node_num) { //查询LCA前的初始化
     69     cnt = 0;
     70     dfs(root, root, 0);
     71     st.init(2 * node_num - 1);
     72 }
     73 
     74 int query_lca(int u, int v) { //查询u,v的lca编号
     75     return F[st.query(P[u], P[v])];
     76 }
     77 
     78 bool flag[MAXN];
     79 
     80 int main() {
     81     int T, N;
     82     int u, v, cnt;
     83     string str_u, str_v;
     84     while(~scanf("%d", &N)) {
     85         init();
     86         cnt = 1;
     87         memset(flag, false, sizeof(flag));
     88         for(int i = 1; i <= N; i++) {
     89             //scanf("%d%d", &u, &v);
     90             cin >> str_u >> str_v;
     91             if (Hash_zh[str_u] == 0) {
     92                 Hash_fa[cnt] = str_u;
     93                 Hash_zh[str_u] = cnt ++;
     94             }
     95             if (Hash_zh[str_v] == 0) {
     96                 Hash_fa[cnt] = str_v;
     97                 Hash_zh[str_v] = cnt ++;
     98             }
     99             u = Hash_zh[str_u];
    100             v = Hash_zh[str_v];
    101             addedge(u, v);
    102             addedge(v, u);
    103             flag[v] = true;
    104         }
    105         int root;
    106         for(int i = 1; i <= N; i++) {
    107             if(!flag[i]) {
    108                 root = i;
    109                 break;
    110             }
    111         }
    112         LCA_init(root, N);
    113         int query_n;
    114         scanf ("%d", &query_n);
    115         for (int i = 1; i <= query_n; ++ i) {
    116             //scanf("%d%d", &u, &v);
    117             cin >> str_u >> str_v;
    118 
    119             if (str_u == str_v) {
    120                 cout << str_u << endl;
    121                 continue;
    122             }
    123 
    124             u = Hash_zh[str_u];
    125             v = Hash_zh[str_v];
    126             cout << Hash_fa[query_lca(u, v)] << endl;
    127         }
    128     }
    129     return 0;
    130 }

    前天晚上自己重新敲了一版,改用struct来存树,结果新代码直接就A掉了,但是还是不知道原来的问题。毕竟想法没错。仍旧是DFS + RMQ的ST。

      1 #include <bits/stdc++.h>
      2 
      3 using namespace std;
      4 
      5 #define MAXN 100005
      6 #define MAXM 105
      7 #define inf 0x7ffffff
      8 int n;
      9 struct Edge {
     10     int v, next;
     11 } edge[MAXN];
     12 int head[MAXN];
     13 int e;
     14 
     15 void addEdge(int u, int v) { //加边
     16     edge[e].v = v;
     17     edge[e].next = head[u];
     18     head[u] = e++;
     19 }
     20 int first[MAXN];//结点在搜索顺序数组中最先出现的位置(下标)
     21 int occur[MAXN << 1]; //结点在出现的顺序数组重复的也要记录
     22 int depth[MAXN << 1]; //结点在搜索树中的深度,与occur相对应
     23 int dp_min[MAXN << 1][20]; //dp_min[i][j] 表示从第i个位置开始的2^j个元素中的最小值的下标
     24 int m = 0; //不断记录出现的下标
     25 
     26 void dfs(int u, int deep) {
     27     occur[++m] = u; //进入该点时进行记录
     28     depth[m] = deep;
     29     if(!first[u])
     30         first[u] = m;
     31     for(int i = head[u]; i + 1; i = edge[i].next) {
     32         dfs(edge[i].v, deep + 1);
     33         occur[++m] = u; //访问子树返回也要标记
     34         depth[m] = deep;
     35     }
     36 }
     37 void init() {
     38     memset(head, -1, sizeof(head));
     39     e = 0;
     40 }
     41 
     42 void RMQ_init(int num) {
     43     for(int i = 1; i <= num; i++)
     44         dp_min[i][0] = i; //注意dp_min存的不是最小值,而是最小值的下标
     45     for(int j = 1; j < 20; j++)
     46         for(int i = 1; i <= num; i++) {
     47             if(i + (1 << j) - 1 <= num) {
     48                 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];
     49             }
     50         }
     51 }
     52 
     53 int RMQ_min(int a, int b) {
     54     int l = first[a], r = first[b]; //得到区间左右端点
     55     if(l > r) {
     56         int t = l;
     57         l = r;
     58         r = t;
     59     }
     60     int k = (int)(log(double(r - l + 1)) / log(2.0));
     61     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]; //最小值下标
     62     return occur[min_id];//取得当前下标表示的结点
     63 }
     64 
     65 map<string, int> Hash_zh;
     66 map<int, string> Hash_fa;
     67 
     68 int main() {
     69     int t, a, b;
     70     init();
     71     m = 0;
     72     memset(first, 0, sizeof(first));
     73     bool in[MAXN];//记录结点有无入度
     74     memset(in, false, sizeof(in));
     75     int u = 0, v = 0, cnt = 1;
     76     string str_u, str_v;
     77     scanf("%d", &n);
     78     for(int i = 1; i <= n; i++) { //注意此题只有n-1条边
     79         cin >> str_u >> str_v;
     80         if (Hash_zh[str_u] == 0) {
     81             Hash_fa[cnt] = str_u;
     82             Hash_zh[str_u] = cnt ++;
     83         }
     84         if (Hash_zh[str_v] == 0) {
     85             Hash_fa[cnt] = str_v;
     86             Hash_zh[str_v] = cnt ++;
     87         }
     88         u = Hash_zh[str_u];
     89         v = Hash_zh[str_v];
     90         addEdge(u, v); //u->v单向
     91         //in[v] = true;
     92     }
     93     dfs(1, 0);
     94     RMQ_init(m);
     95     int op_n;
     96     scanf ("%d", &op_n);
     97     while (op_n --) {
     98         cin >> str_u >> str_v;
     99         if (str_u == str_v) {
    100             cout << str_u << endl;
    101             continue;
    102         }
    103         u = Hash_zh[str_u];
    104         v = Hash_zh[str_v];
    105         cout << Hash_fa[RMQ_min(u, v)] << endl;
    106     }
    107 
    108     return 0;
    109 }
  • 相关阅读:
    分布式消息系统Kafka初步
    webService 学习
    一个周末掌握IT前沿技术之node.js篇
    mount
    dd
    fsck
    resize2fs
    mkfs
    parted
    tune2fs
  • 原文地址:https://www.cnblogs.com/Destiny-Gem/p/4025548.html
Copyright © 2011-2022 走看看