【问题标题】:Count number of cycles in directed graph using DFS使用 DFS 计算有向图中的循环数
【发布时间】:2016-01-27 01:13:21
【问题描述】:

我想计算有向图中可用的有向循环总数(只需要计数)。

您可以假设图形作为邻接矩阵给出。

我知道DFS,但无法为这个问题制定一个可行的算法。

请提供一些使用DFS的伪代码。

【问题讨论】:

  • DFS 不是只适用于无环图吗...?否则,您将永远继续潜水和潜水。

标签: algorithm graph cycle depth-first-search directed-graph


【解决方案1】:

让我们考虑一下,我们用三种颜色为节点着色。如果节点尚未被发现,则其颜色为白色。如果节点被发现但其任何后代尚未被发现,则其颜色为灰色。否则它的颜色是黑色的。现在,在进行 DFS 时,如果我们遇到这样一种情况,两个灰色节点之间有一条边,那么图就有了循环。循环的总数将是我们面对上述情况的总次数,即我们在两个灰色节点之间找到一条边。

【讨论】:

  • 在深度优先搜索中,每个有向边仅被考虑一次,因此该算法给出的循环数少于边数。不幸的是,可能有比边更多的周期。考虑 n 个顶点上的完整图。两个或多个顶点的每个子集至少描述一个循环 [(n-1)!其中实际上],但只有 n*(n-1) 条边,因此周期数增长速度比 2^n 快,但边数没有。所以上面的算法是行不通的。
【解决方案2】:

这个基于DFS的算法貌似可行,但我没有证据。

这个算法是从dfs修改而来的,用于拓扑排序 (https://en.wikipedia.org/wiki/Topological_sorting#Depth-first_search)。

class Solution {
  vector<Edge> edges;
  // graph[vertex_id] -> vector of index of outgoing edges from @vertex_id.
  vector<vector<int>> graph;
  vector<bool> mark;
  vector<bool> pmark;
  int cycles;

  void dfs(int node) {
    if (pmark[node]) {
      return;
    }
    if (mark[node]) {
      cycles++;
      return;
    }
    mark[node] = true;

    // Try all outgoing edges.
    for (int edge_index : graph[node]) {
      dfs(edges[edge_index].to);
    }

    pmark[node] = true;
    mark[node] = false;
  }

  int CountCycles() {
    // Build graph.
    // ...

    cycles = 0;
    mark = vector<bool>(graph.size(), false);
    pmark = vector<bool>(graph.size(), false);
    for (int i = 0; i < (int) graph.size(); i++) {
      dfs(i);
    }

    return cycles;
  }
};

【讨论】:

    猜你喜欢
    • 2021-09-23
    • 2018-08-19
    • 2017-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-21
    • 2016-01-30
    相关资源
    最近更新 更多