zoukankan      html  css  js  c++  java
  • poj1330 Nearest Common Ancestors **

    /*
    * poj-1330.cpp
    * LCA
    *
    * LCA入门题
    *
    * 没有用tarjan的离线算法, 用了个在线的, 时间复杂度O(n)-O(sqrt(n))
    *
    * height为树的高度
    * 把树按层次分成sqrt(height)个段,每段sqrt(height)层。
    *
    * 对LCA(x, y)
    * 先把x, y 导入到同一段, 由于最多sqrt(height)段, 所以O(sqrt(height))
    * 再在同一段内, 按普通方法找到x, y的LCA, 由于每段sart(height)层, 所以O(sqrt(height))
    * 故查询时间为 O(sqrt(height)) = O(sqrt(n))
    *
    * Created on: 2011-10-16
    */
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    using namespace std;

    const int maxN = 10000 + 10;

    //secHeight每段的层数
    int caseNum, n, root, height, secHeight;
    //f[x]: x的父节点, layer[x]:x层数, p[x]:x在上一段中的祖先
    int f[maxN], layer[maxN], stack[maxN], p[maxN];
    bool isCreated[maxN];
    //邻接表节点
    struct SNode{
    int key;
    SNode *list;

    SNode(int _key): key(_key), list(NULL) {}
    };
    SNode *tree[maxN];

    //深搜计算layer[], 用栈实现
    void calLayer(){
    int top = 0, cur = root;
    SNode *curNode;
    layer[cur] = 0;

    stack[top++] = cur;
    while(top != 0){
    cur = stack[--top];
    curNode = tree[cur]->list;
    while(curNode != NULL){
    layer[curNode->key] = layer[cur] + 1;
    stack[top++] = curNode->key;

    curNode = curNode->list;
    }
    }
    height = layer[cur];
    }

    //计算p数组
    void dfs(int cur){
    //第一段的节点 p = root
    if(layer[cur] < secHeight)
    p[cur] = root;
    else if(layer[cur] % secHeight == 0)
    p[cur] = f[cur];
    else
    p[cur] = p[f[cur]];

    SNode *tmpNode = tree[cur]->list;
    while(tmpNode != NULL){
    dfs(tmpNode->key);

    tmpNode = tmpNode->list;
    }
    }


    //lca(x, y)
    int LCA(int x, int y){
    //让x和y到达同一段
    while(p[x] != p[y]){
    if(layer[x] > layer[y])
    x = p[x];
    else
    y = p[y];
    }

    //按普通方法求lca
    while(x != y){
    if(layer[x] > layer[y])
    x = f[x];
    else
    y = f[y];
    }

    return x;
    }


    int main(){
    scanf("%d", &caseNum);
    while(caseNum--){
    scanf("%d", &n);

    memset(isCreated, 0, sizeof(isCreated));
    memset(f, -1, sizeof(f));
    height = -1;

    //输入,建树
    int u, v;
    SNode *tmpNode;
    for(int i=1; i<n; i++){
    scanf("%d %d", &u, &v);
    if(!isCreated[u]){
    tree[u] = new SNode(u);
    isCreated[u] = 1;
    }
    if(!isCreated[v]){
    tree[v] = new SNode(v);
    isCreated[v] = 1;
    }

    tmpNode = new SNode(v);
    tmpNode->list = tree[u]->list;
    tree[u]->list = tmpNode;

    f[v] = u;
    }

    //找到树根
    for(int i=1; i<n; i++)
    if(f[i] == -1){
    root = i; break;
    }

    //计算各节点的层数
    calLayer();
    //每个分段的层数
    secHeight = (int)sqrt(height + 0.0);

    //计算p数组
    dfs(root);

    scanf("%d %d", &u, &v);
    printf("%d\n", LCA(u, v));

    }


    return 0;
    }
  • 相关阅读:
    DOS命令大全(二)
    读取本地Json文件
    微信接入详细流程 分享给好友和朋友圈
    IOS开发中(null)与<null>的处理
    iOS 删除NSString中特定字符
    float类型转对象 对象转float类型(一)
    真机调试出现Could not find Developer Disk Image问题解决办法
    iOS开发融云即时通讯集成详细步骤
    UITableVIew 滚动流畅性优化
    Python装饰器
  • 原文地址:https://www.cnblogs.com/longdouhzt/p/2214031.html
Copyright © 2011-2022 走看看