zoukankan      html  css  js  c++  java
  • POJ 1330 Nearest Common Ancestors【LCA】

    题目链接:

    http://poj.org/problem?id=1330

    题意:

    裸的LCA

    代码:

    倍增:

    #include<iostream>
    #include<cstring>
    using namespace std;
    const int maxn = 10005;
    const int maxm = 20;
    struct Edge{int to, next;};
    Edge edge[maxn * 2];
    int head[maxn], tot;
    int pa[maxm][maxn];
    int dept[maxn], in[maxn];
    int root, V;
    void add_edge(int u, int v)
    {
        edge[tot].to = v;
        edge[tot].next = head[u];
        head[u] = tot++;
    }
    void initedge()
    {
        tot = 0;
        memset(head, -1, sizeof(head));
    }
    //DFS预处理所有结点的深度和父节点
    void dfs(int v, int p, int d)
    {
        pa[0][v] = p;
        dept[v] = d;
        for(int i = head[v]; i != -1; i = edge[i].next){
            int u = edge[i].to;
            if(u == p) continue;
            dfs(u, v, d + 1);
        }
    }
    void init()
    {
        dfs(root, -1, 0);
        //预处理祖先,向上走2^i所到的结点
        for(int i = 0; i < maxm - 1; i++){
            for(int j = 1; j <= V; j++){
                if(pa[i][j] < 0) pa[i + 1][j] = -1;
                else pa[i + 1][j] = pa[i][pa[i][j]];
            }
        }
    }
    int lca(int u, int v)
    {
        //让u和v 向上走到同一高度
        if(dept[u] > dept[v]) swap(u, v);
        for(int i = 0; i < maxm; i++){
            if((dept[v] - dept[u]) >>i &1)
                v = pa[i][v];
        }
        if(u == v) return u;
    
        //二分搜索计算lca
        for(int i = maxm - 1; i >= 0; i--){
            if(pa[i][u] != pa[i][v]){
                u = pa[i][u];
                v = pa[i][v];
            }
        }
        return pa[0][u];
    }
    int main(void)
    {
        int T;cin>>T;
        int u, v;
        while(T--){
            cin>>V;
            initedge();
            memset(in, 0, sizeof(in));
            for(int i = 1; i < V; i++){
                cin>>u>>v;
                add_edge(u, v);
                add_edge(v, u);
                in[v] = 1;
            }
            for(root = 1; root <= V; root++){
                if(!in[root]) break;
            }
            init();
            cin>>u>>v;
            cout<<lca(u, v)<<endl;;
        }
        return 0;

    RMQ:

    (照着bin神的模板敲的

    #include<iostream>
    #include<cstring>
    #include<cmath>
    using namespace std;
    const int maxn = 10005;
    const int maxm = 20;
    struct Edge{int to, next;};
    Edge edge[maxn * 2];
    int head[maxn], tot;
    int pa[maxm][maxn];
    int dept[maxn], in[maxn];
    int root, V, cnt;
    int vs[maxn * 2], id[maxn];
    int rmq[2 * maxn];
    void add_edge(int u, int v)
    {
        edge[tot].to = v;
        edge[tot].next = head[u];
        head[u] = tot++;
    }
    void initedge()
    {
        tot = 0;
        memset(head, -1, sizeof(head));
    }
    struct ST
    {
        int lg[2 * maxn];
        int dp[2 * maxn][20];//最小值对应下标
        void init(int n){
            lg[0] = -1;
            for(int i = 1; i <= n; i++){
                lg[i] = ((i & (i - 1)) == 0)?lg[i - 1] + 1:lg[i - 1];
                dp[i][0] = i;
            }
            for(int j = 1; j <= lg[n]; j++){
                for(int i = 1; i + (1<<j) - 1 <= n; i++){
                    if(rmq[dp[i][j - 1]] < rmq[dp[i + (1<<(j - 1))][j - 1]])
                        dp[i][j] = dp[i][j - 1];
                    else dp[i][j] = dp[i + (1<<(j - 1))][j - 1];
                }
            }
        }
        int query(int a, int b){
            if(a > b) swap(a, b);
            int k = lg[b - a + 1] ;
           // cout<<b<<' '<<a<<endl;
            if(rmq[dp[a][k]] <= rmq[dp[b - (1<<k) + 1][k]])
                return dp[a][k];
            else return dp[b - (1<<k) + 1][k];
        }
    };
    ST st;
    //vs dfs的访问顺序
    void dfs(int u, int pre, int dept)
    {
        vs[++cnt] = u;
        rmq[cnt] = dept;
        id[u] = cnt;
        int fro = head[u];
        while(fro != -1){
            dfs(edge[fro].to, u, dept + 1);
            fro = edge[fro].next;
            vs[++cnt] = u;
            rmq[cnt] = dept;
        }
    }
    void init()
    {
        cnt = 0;
        dfs(root, root, 0);
        st.init(2 * V - 1);
    }
    int lca(int u, int v)
    {
        return vs[st.query(id[u], id[v])];
    }
    int main(void)
    {
        int T;cin>>T;
        int u, v;
        while(T--){
            cin>>V;
            initedge();
            memset(in, 0, sizeof(in));
            for(int i = 1; i < V; i++){
                cin>>u>>v;
                add_edge(u, v);
                in[v] = 1;
            }
            for(root = 1; root <= V; root++){
                if(!in[root]) break;
            }
            init();
            cin>>u>>v;
            cout<<lca(u, v)<<endl;;
        }
        return 0;
    }
  • 相关阅读:
    php解决前端调接口跨域问题
    降低token 被盗风险安全问题
    u盘怎么解除写保护状态,u盘写保护怎么去掉
    安装vsftpd时出现错误
    对于vim 编译器的设置
    Vim 怎么设置显示行号,永久性显示行号
    Ubuntu系统设置过程中信息显示不全
    控制文件夹名显示的长短
    linux中好玩的游戏
    安装VMware Tools
  • 原文地址:https://www.cnblogs.com/Tuesdayzz/p/5758699.html
Copyright © 2011-2022 走看看