在树检查中,给定节点是否是另一个节点的祖先

时间:2018-03-11 03:43:15

标签: c++ algorithm graph tree depth-first-search

我有一个问题 - 如果给定2个节点(A,B)是B的祖先,我需要回答问题。我知道可能的解决方案是获取进入节点的时间和我离开的时间它。基于此,我可以快速计算关系。如何获得这些时间戳'使用无法使用重复实现的DFS?

我不是算法和C ++的专家,这就是我要问的原因。

2 个答案:

答案 0 :(得分:1)

使用标准的扩充线程索引(ATI - 参见下面提供的参考),它提供节点长度数据结构,通常是数组,回答AB是否为pred的问题祖先在不变的时间是不可能的。

如果您存储每个节点的threaddepthA(构成ATI方案中的基本数据结构),那么B是否为O(N)的问题B的祖先可以在pred时间内完成 - 只需使用root数据结构从A回溯,直至到达ancestor和检查您是否遇到if ($school->set_specialties !== null) { $school->touch(); }

但是,您可以为每个节点执行上述操作作为预处理步骤,然后为每个节点创建一个新的节点长度数组{ "error": { "message": "This Person Cannot Receive Messages: This person isn't receiving messages from you right now.", "type": "OAuthException", "code": 10, "error_subcode": 2018108, "fbtrace_id": "BLBz/WZt8dN" } } ,指示另一个节点是否是其祖先。

参考:Bazaara, Jarvis and Sherali第482页。

答案 1 :(得分:0)

我找到了获得它的方法。如果您的树在邻接列表中,那么您可以进行预处理。对于每个节点您需要在输入时以及在DFS期间离开时分配值,然后在恒定时间内进行检查:

if (timeIn[b] >= timeIn[a] && timeIn[b] <= timeOut[a]) {
   printf("YES\n");
}
else {
   printf("NO\n");
}

其中a是b的祖先。

DFS:

// INITIALIZE VARs
int time = 0;
stack<int> stackOfChildNodes;
// put root of tree
stackOfChildNodes.push(first);
// go with DFS
while (!stackOfChildNodes.empty()) {
    int current = stackOfChildNodes.top();
    stackOfChildNodes.pop();
    // if node was not visited (time is not set)
    if (timeIn[current] == -1) {
        timeIn[current] = time; // node visited
        time++; // increase time to go further
        stackOfChildNodes.push(current); // include node in processing to leave it in future
        int child = children[current];
        // add descendants to process them
        while (child != 0) {
            stackOfChildNodes.push(child);
            child = descendants[child];
        }
    }
    // if node was visited, so we gonna leave him now
    if (timeIn[current] != -1) {
        timeOut[current] = time-1;
    }
}