c++ - 有向图中两个给定节点的最近交汇点

标签 c++ algorithm directed-graph

我有一个有向图和其中的两个节点,我需要找到可以从这两个节点到达的最近节点。唯一的问题是我可以用两个 dfs 来完成,但我被告知要在 O(logn) 中完成。附加约束是每个单元格可以有至多一个出边。输入以大小为 N 的数组形式给出,其中数组中的每个条目表示该节点指向的节点的索引。所以这是我试过的代码(不完全是 dfs 但仍然):

int leastCommonDescendent(int nodes[], int N, int node1, int node2)
{
  int *visited = new int [N];
  int cnt1 = 0; //used for counting length of path from node1 to node2
  int cnt2 = 0; //used for counting length of path from node2 to node1
  int mark = node1; //storing as a marker needed later for detecting end of search

  if(node1 == node2) return node2;
  for(int i = 0; i < N; i++){
    visited[i] = 0;
  }

  while((nodes[node1] != node1) && (nodes[node1] != -1) && (visited[node1] == 0) && (node1 != node2)){
    visited[node1]++;
    node1 = nodes[node1];
    cnt1++;
  }

  visited[node1]++; //so that first node in cycle has count 2
                    //if find a node in 2nd iteration that has count 2
                    //such that when node1 == node2 it means we are in the same subgraph
                    //elsif node1 != node2 we are in different sub graphs

  while((nodes[node2] != node2) && (nodes[node2] != -1) && (visited[node2] != 2) && (node1 != node2)){
    visited[node2]++;
    node2 = nodes[node2];
    cnt2++;
  }
  //In below case the nodes are in different disjoint subgraphs
  //and both subgraphs have loops so node1 can never be equal to node2
  //cout << visited[node1] << visited[node2] << endl;
  if(node1 != node2) return -1;
    //In below case both nodes are in different disjoint subgraphs
    //but there is no loop in 1st one(containing node1)
    //and 2nd one has a loop
  if ((nodes[node1] == -1) && (visited[node2] == 1)) return -1;
    //In below case both nodes are in different disjoint subgraphs
    //but 1st one has a loop and second one doesn't
  if(nodes[node2] == -1) return -1;
    //In below case both nodes are in same subgraph so we
    //need to check the length of two alternate paths
  if(cnt1 > cnt2)
    return node2;
  else
    return mark;
}  

假设我有一个图的组成部分(本质上是一个子图),如下所示:
enter image description here

在这种情况下,如果我想从 7 和 9 中找到最近的节点,我会得到答案 9,而它应该是 8。虽然我明白这是因为我在两个循环中都有条件 cell1 != cell2 但我要对于整个周期,以防我删除邀请更多时间的内容。此外,我觉得这个解决方案与多个 if's 杂乱无章。我们可以有一个更简单的解决方案吗? (可能基于O(logn))

这个图也可以有循环,如上图所示。所以我猜想转换成树是不可能的。

最佳答案

这很容易减少到(和从)Lowest Common Ancestor in a tree (或者准确地说是在森林中),只需反转图表的链接即可。

一般来说,它可以在 O(h) 中完成,通过逐步“向上”树(在原始图中向前),并将找到的节点存储在一个集合中,直到设置交叉点不为空。

如果允许预处理,可以在线性时间内进行预处理,以获得更好的结果。

关于c++ - 有向图中两个给定节点的最近交汇点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35078409/

相关文章:

c++ - 如何更改 C++ 对象的类(实现可变类型)

algorithm - 完整的二叉树定义

java - 计算没有两个相邻字符相同的所有排列

algorithm - 设计单源最短路径问题的算法

graphviz - 我怎样才能得到点来并排绘制连接的子图?

指针和结构的 C++ 邻接表

c++ - 多态基类指针

c++ - 从字节流中提取字节

c++ - 在构建库之前选择选项

algorithm - 查找非边缘相交的最短路径的数量