我有一个无向图,它被加载为邻接矩阵。我有一个使用BFS算法检测图中循环的方法。我试图实现的是打印所有的边缘,以一种方式,他们表明一个循环,已经找到。
我可以打印一个图形中的所有边,但我不能只打印那些创建循环的边。我怎么让它工作?
边缘:
public class Edge {
int source, dest;
public Edge(int source, int dest) {
this.source = source;
this.dest = dest;
}
}
图表:
public class Graph {
// A List of Lists to represent an adjacency list
// Each insideList contains pointers to the next vertex
// list with an index of 1 (vertex 1) contains elements 2 and 3 (where 2, 3 are vertices connected to 1)
List<List<Integer>> adjList = null;
// Constructor
public Graph(List<Edge> edges, int N) {
adjList = new ArrayList<>(N);
for (int i = 0; i < N; i++) {
adjList.add(i, new ArrayList<>());
}
// add edges to the undirected graph
for (Edge edge : edges) {
int src = edge.source;
int dest = edge.dest;
adjList.get(src).add(dest);
adjList.get(dest).add(src);
}
}
}
节点:
public class Node {
int v, parent;
public Node(int v, int parent) {
this.v = v;
this.parent = parent;
}
}
public class GraphTest {
// Perform BFS on graph starting from vertex src and
// returns true if cycle is found in the graph
// while traversing the graph, it should display the edges which create a cycle, but I am unable to do it (the result is wrong)
public static boolean BFS(Graph graph, int src, int N) {
// stores booleans if a vertex is discovered or not
boolean[] discovered = new boolean[N];
// mark source vertex as discovered
discovered[src] = true;
// create a queue used to do BFS and
// push source vertex into the queue
Queue<Node> q = new ArrayDeque<>();
q.add(new Node(src, -1));
// run till queue is not empty
while (!q.isEmpty()) {
// pop front node from queue and print it
Node node = q.poll();
// do for every edge (v -> u)
for (int u : graph.adjList.get(node.v)) {
if (!discovered[u]) {
// mark it as discovered
discovered[u] = true;
// construct the queue node containing info
// about vertex and push it into the queue
System.out.println(node.v + " -- " + u);
q.add(new Node(u, node.v));
}
// u is discovered and u is not a parent
else if (u != node.parent) {
// we found a cross-edge ie. cycle is found
return true;
}
}
}
// No cross-edges found in the graph
return false;
}
// Check if an undirected graph contains cycle or not
public static void main(String[] args) {
// In my case I load an adjacency matrix from file and then perform an action to create Edges.
// 0 1 1 0
// 1 0 1 0
// 1 1 0 1
// 0 0 1 0
// Edge(1, 2), Edge(2, 3), Edge(3, 1), Edge(3, 4)
// Edge(3, 1) introduces a cycle in the graph
List<Edge> edges = new ArrayList<Edge>();
ArrayList<ArrayList<Integer>> matrixList = loadFromFile(filePath);
System.out.println("Graph: (Adjacency Matrix)");
for (int i = 0; i < matrixList.size(); i++) {
for (int j = 0; j < matrixList.size(); j++) {
System.out.print(matrixList.get(i).get(j) + " ");
}
System.out.println();
}
System.out.println("All the edges: ");
for (int i = 0; i < matrixList.size(); i++) {
// ' + 1' is added so as to start vertices from 1 instead of 0
int temp = i + 1;
for (int j = 0; j < matrixList.size(); j++) {
if (matrixList.get(i).get(j) == 1) {
System.out.println(temp + "--" + (j + 1) + " ");
// each edge is added one-way only since it is an undirected graph
// if Edge(1,3) is already present, Edge(3,1) is not added
boolean isFound = false;
for (Edge e : edges) {
if (e.dest == temp && e.source == (j + 1)) {
isFound = true;
}
}
if (!isFound)
edges.add(new Edge(temp, j + 1));
}
}
System.out.println();
}
// sets number of vertices in the graph
final int N = 5;
// creates a graph from edges
Graph graph = new Graph(edges, N);
boolean[] discovered = new boolean[N];
// do BFS traversal in connected components of graph
System.out.println("Detect a cycle: ");
if (BFS(graph, 1, N))
System.out.println("Graph contains cycle");
else
System.out.println("Graph doesn't contain any cycle");
}
当前错误输出:显示一个周期的部分边沿,但不是全部边沿
预期输出:打印创建循环的所有边,如上面的示例所示,
我想显示:1--2,2--3,3--1
一条边的结束顶点是循环中另一条边的起始顶点。
我不是说这是达到结果的最好方法,但这是方法之一。
首先,我要更改节点的定义:
public class Node {
int v;
Node parent;
public Node(int v, Node parent) {
this.v = v;
this.parent = parent;
}
}
然后在您的方法BFS中,我将发现的布尔数组更改为节点数组,这样您就知道了,哪个路径通向这个节点。
// stores booleans if a vertex is discovered or not
Node[] discovered = new Node[N];
public static boolean BFS(Graph graph, int src, int N) {
// stores booleans if a vertex is discovered or not
Node[] discovered = new Node[N];
// mark source vertex as discovered
Node start = new Node(src, null);
discovered[src] = start;
// create a queue used to do BFS and
// push source vertex into the queue
Queue<Node> q = new LinkedList<>();
q.add(start);
// run till queue is not empty
while (!q.isEmpty()) {
// pop front node from queue and print it
Node node = q.poll();
// do for every edge (v -> u)
for (int u : graph.adjList.get(node.v)) {
if (discovered[u] == null) {
// mark it as discovered
Node newNode = new Node(u, node);
discovered[u] = newNode;
// construct the queue node containing info
// about vertex and push it into the queue
q.add(newNode);
}
// u is discovered and u is not a parent
else if (u != node.parent.v) {
Node newNode = new Node(u, node);
int commonParent = findCommonParent(discovered[u], newNode);
String result = "";
Node current;
current = discovered[u];
while(current.v != commonParent) {
result = current.parent.v + "--" + current.v + ", " + result;
current = current.parent;
}
current = newNode;
while(current.v != commonParent) {
result = result + current.v + "--" + current.parent.v + ", ";
current = current.parent;
}
result = result.substring(0, result.length() - 2);
System.out.println(result);
// we found a cross-edge ie. cycle is found
return true;
}
}
}
// No cross-edges found in the graph
return false;
}
方法findCommonParent可以实现,例如如下所示:
private static int findCommonParent(Node n1, Node n2) {
Set<Integer> n1Parents = new HashSet<Integer>();
Node temp = n1.parent;
while(temp != null) {
n1Parents.add(temp.v);
temp = temp.parent;
}
temp = n2.parent;
while(temp != null) {
if(n1Parents.contains(temp.v)) {
break;
}
temp = temp.parent;
}
return temp.v;
}
我们可以用这里所述的算法求有向图中的圈数。我需要理解算法。 (1)最后那句话到底有什么用处?对algo的工作原理进行简短的描述会很有帮助。由于算法基本上是统计从一个节点返回到同一节点的周期数,所以我们可以使用另一个数组,称之为v,并做以下技巧: (2)我不能实现我刚才写的算法。这是主要的问题,但我认为我需要理解上面的(1)来理解打印所有循环的代码。 我了解到互联网上有算法,我正在尝试使用这个算法。
如何在有向加权图中找到负循环。我知道Bellman-Ford算法是如何工作的,它告诉我是否存在可达到的负循环。但它没有明确地命名它。 如何获得循环的实际路径v1,v2,…vk,v1? 在应用标准算法后,我们已经进行了n−1次迭代,不可能有进一步的改进。如果我们仍然可以降低到节点的距离,则存在负循环。 假设edge(v, u)是bellman ford算法在第n次迭代中失败的边缘-d(u)
问题内容: 是否可以打印字符串“ x”次? 例如,如果给定字符串 假设用户输入数字“ 4”,表示他们希望重复字符串的次数。 该程序将打印: 问题答案: 您可以像这样使用递归 并最初调用这样的方法-
目前我正在用这个样本进行拓扑排序,并对https://www.geeksforgeeks.org/topological-sorting/做了一些修改 我用它来排序要求解的变量的顺序。 样本 每个变量都有一个唯一整数,并存储在一个映射中 创建图形并添加边时,总共有4个顶点,因此我的代码将像这样构造图形 排序并按相反顺序得到结果后,它是正确的c 一切都很好,但我需要检测图中的循环引用。假设变量是 有
因此,我为DFS编写了以下代码: 现在,我读到,在一个无向图中,如果当DFS时,它再次返回到同一个顶点,有一个循环。所以我做的是这样,, 但是,我的检查周期函数返回true,即使他们没有周期。那是为什么呢?我的功能有问题吗?没有执行问题,否则我早就调试了,但他们似乎在我的逻辑中有问题。
问题内容: 打印从1到1000的数字,而不使用任何循环或条件语句。不要只写printf()orcout语句1000次。 您将如何使用C或C ++做到这一点? 问题答案: 编译时间递归!:P