您的位置:首页 > 其它

POJ - 1330 Nearest Common Ancestors(LCA在线查询)

2015-09-12 17:13 489 查看
题目大意:给你一棵树,要求你输出两个点的LCA

解题思路:模版题

[code]#include <cstdio>
#include <cstring>
const int MAXNODE = 100010;
const int MAXEDGE = 200010;

struct Edge {
    int u, v, next;
    Edge() {}
    Edge(int u, int v, int next): u(u), v(v), next(next) {}
};

struct ST {
    Edge edges[MAXEDGE];
    int n, m, tot;
    int head[MAXNODE], depth[MAXNODE], first[MAXNODE], ver[MAXNODE];
    int dp[MAXNODE][64];
    bool vis[MAXNODE];

    void init(int n) {
        this->n = n;
        m = tot = 0;
        memset(head, -1, sizeof(head));
        memset(vis, 0, sizeof(vis));
    }

    void AddEdge(int u, int v) {
        edges[m] = Edge(u, v, head[u]);
        head[u] = m++;
    }

    //ver记录的是第tot个结点是哪个,first记录的是结点u第一次出现的位置,depth记录的是第tot个结点的深度
    void dfs(int u, int dep) {
        vis[u] = true; ver[++tot] = u; first[u] = tot; depth[tot] = dep;
        for (int i = head[u]; ~i; i = edges[i].next) {
            int v = edges[i].v;
            if (!vis[v]) {
                dfs(v, dep + 1);
                ver[++tot] = u; depth[tot] = dep;
            }
        }
    }

    void RMQ() {

        //dp记录的是下标从i开始,长度为2的j次方这段区间内深度最小的点是ver中的第几个
        for (int i = 1; i <= tot; i++)
            dp[i][0] = i;
        int a, b;
        for (int j = 1; (1 << j) <= tot; j++) 
            for (int i = 1; i + (1 << j) - 1 <= tot; i++) {
                a = dp[i][j - 1];
                b = dp[i + (1 << (j - 1))][j - 1];
                if (depth[a] < depth[b]) 
                    dp[i][j] = a;
                else
                    dp[i][j] = b;
            }
    }

    void solve(int root) {
        dfs(root, 1);
        RMQ();
    }

    //查询区间[x,y]中深度最小的那个数的位置
    int Query(int x, int y) {
        int k = 0;
        while (1 << (k + 1) <= y - x + 1) k++;
        int a = dp[x][k];
        int b = dp[y - (1 << k) + 1][k];
        if (depth[a] < depth[b]) return a;
        return b;
    }

    int LCA(int x, int y) {
        x = first[x];
        y = first[y];
        if (x > y) {
            x = x ^ y; y = x ^ y; x = x ^ y;
        }
        int c = Query(x, y);
        return ver[c];
    }

}st;

const int N = 10010;
bool vis
;
int n;

void init() {
    scanf("%d", &n);
    st.init(n);
    memset(vis, 0, sizeof(vis));

    int u, v;
    for (int i = 1; i < n; i++) {
        scanf("%d%d", &u, &v);
        st.AddEdge(u, v);
        vis[v] = true;
    }

    for (int i = 1; i <= n; i++)
        if (!vis[i]) {
            st.solve(i);
            break;
        }
    scanf("%d%d", &u, &v);
    printf("%d\n", st.LCA(u, v));
}

int main() {
    int test;
    scanf("%d", &test);
    while (test--) {
        init();
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: