我有一个问题 - 如果给定2个节点(A,B)是B的祖先,我需要回答问题。我知道可能的解决方案是获取进入节点的时间和我离开的时间它。基于此,我可以快速计算关系。如何获得这些时间戳'使用无法使用重复实现的DFS?
我不是算法和C ++的专家,这就是我要问的原因。
答案 0 :(得分:1)
使用标准的扩充线程索引(ATI - 参见下面提供的参考),它提供节点长度数据结构,通常是数组,回答A
是B
是否为pred
的问题祖先在不变的时间是不可能的。
如果您存储每个节点的thread
,depth
和A
(构成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;
}
}