用于检测图中循环的算法的修改
Posted
技术标签:
【中文标题】用于检测图中循环的算法的修改【英文标题】:Modification of an algorithm for detecting cycles in a graph 【发布时间】:2015-07-31 14:00:09 【问题描述】:在下面的代码中,我检查图形是否包含循环并且它正在 100% 工作,但我确实想修改它,而不是打印是的,我希望它打印循环重复的第一个节点.因此,例如,如果实际图形有一个循环并且循环是 0,1,3,5,7,0 ,而不是我想打印 0。 或者如果循环是 1、3、5、7、8、1,它应该打印 1。如果有人知道我会很感激,谢谢。
#include<iostream>
#include <list>
#include <limits.h>
using namespace std;
// Class for an undirected graph
class Graph
int V; // No. of vertices
list<int> *adj; // Pointer to an array containing adjacency lists
bool isCyclicUtil(int v, bool visited[], int parent);
public:
Graph(int V); // Constructor
void addEdge(int v, int w); // to add an edge to graph
bool isCyclic(); // returns true if there is a cycle
;
Graph::Graph(int V)
this->V = V;
adj = new list<int>[V];
void Graph::addEdge(int v, int w)
adj[v].push_back(w); // Add w to v’s list.
adj[w].push_back(v); // Add v to w’s list.
// A recursive function that uses visited[] and parent to detect
// cycle in subgraph reachable from vertex v.
bool Graph::isCyclicUtil(int v, bool visited[], int parent)
// Mark the current node as visited
visited[v] = true;
// Recur for all the vertices adjacent to this vertex
list<int>::iterator i;
for (i = adj[v].begin(); i != adj[v].end(); ++i)
// If an adjacent is not visited, then recur for that adjacent
if (!visited[*i])
if (isCyclicUtil(*i, visited, v))
return true;
// If an adjacent is visited and not parent of current vertex,
// then there is a cycle.
else if (*i != parent)
return true;
return false;
// Returns true if the graph contains a cycle, else false.
bool Graph::isCyclic()
// Mark all the vertices as not visited and not part of recursion
// stack
bool *visited = new bool[V];
for (int i = 0; i < V; i++)
visited[i] = false;
// Call the recursive helper function to detect cycle in different
// DFS trees
for (int u = 0; u < V; u++)
if (!visited[u]) // Don't recur for u if it is already visited
if (isCyclicUtil(u, visited, -1))
return true;
return false;
// Driver program to test above functions
int main()
int res=0;
int m, n;
cin >> m >> n;
Graph g1(m);
for(int i=0; i<n; i++)
int q, r;
cin >> q >> r;
g1.addEdge(q, r);
g1.isCyclic()? cout << "Yes":
cout << "No";
return 0;
【问题讨论】:
什么是循环的开始?循环本身没有开始。在您的示例中,如果 0、1、3、5、7、0 是一个循环 0 是第一个元素,就像 3 或 7 一样 我的意思是在这种情况下重复的第一个元素 0 是第一个重复的元素。或者如果有一个循环 1,6,7,8,9,8 ,它应该打印 8,我认为现在很清楚 :) 这是作业吗?是什么阻碍了您仅打印它? 不,不是。第一个元素取决于您开始搜索的位置。在您的第二个示例中,您可以有另一条路径首先通向 9(而不是 8)。我想说的是'第一个'lelement没有明确定义。也许您需要告诉我们更多关于“为什么”需要它的信息。 @kchoi 我很确定“循环”应该是指从 X 到 Y 的两条不同路径(概念上是从 X 到 Y 的路径和从 Y 到 X 的路径,而不是从X 到 Y)。 【参考方案1】:一旦你找到一个循环,通过访问一个你已经访问过的节点,你就知道这个节点是循环的一部分。 然后你可以对节点本身进行深度优先搜索。找到后,输出堆栈上的所有节点。
如果您想高效地编写代码,您也可以通过这种方式找到循环,然后输出所有节点,直到到达找到循环的节点。
【讨论】:
请求是在一个循环中输出“第一个”(无论是什么意思)项目。但是您的答案旨在输出一个循环中的所有项目,即使这样,您也可能是错误的(将输出循环的父项)或缺少很多细节。 我的解决方案输出循环的所有项目。循环中没有“第一个”项目。但是,它不会输出除循环元素之外的任何其他元素(父级)。如果您的意思是“更有效”的方法:您首先深度搜索循环。一旦你找到一个循环,你标记你所在的项目,把它写出来并返回一些东西,告诉你的递归函数找到了一个循环,它应该输出它所在的元素,然后再次返回,......除非你的堆栈在标记节点处,循环结束(并因此开始)。那么这个循环就完成了。【参考方案2】:找到一个逻辑顺序(或者只是序列化搜索顺序)并使用哈希来重复节点和已经看到的循环。打印搜索开始节点号。根据您的搜索顺序,您的结果可能会有所不同。
【讨论】:
以上是关于用于检测图中循环的算法的修改的主要内容,如果未能解决你的问题,请参考以下文章