簡體   English   中英

DFS算法檢測圖形中的周期

[英]DFS algorithm to detect cycles in graph

#include <iostream>
#include <vector>
#include <stack>
using namespace std;

class Graph{
        public:
            vector<int> adjList[10001];
            void addEdge(int u,int v){
                adjList[u].push_back(v);
                adjList[v].push_back(u);
            }
};

bool dfs(Graph graph, int n){
    vector<int> neighbors;
    int curr,parent;
    bool visited[10001] = {0};
    stack<int> s;
    //Depth First Search
    s.push(1);
    parent = 0;
    while(!s.empty()){
        curr = s.top();
        neighbors = graph.adjList[curr];
        s.pop();
        //If current is unvisited
        if(visited[curr] == false){
            for(int j=0; j<neighbors.size(); j++){
                //If node connected to itself, then cycle exists
                if(neighbors[j] == curr){
                    return false;;
                }
                else if(visited[neighbors[j]] == false){
                    s.push(neighbors[j]);
                }
                //If the neighbor is already visited, and it is not a parent, then cycle is detected
                else if(visited[neighbors[j]] == true && neighbors[j] != parent){
                    return false;
                }
            }
            //Mark as visited
            visited[curr] = true;
            parent = curr;
        }
    }
    //Checking if graph is fully connected
    for(int i=1; i<=n; i++){
        if(visited[i] == false){
            return false;
        }
    }
    //Only if there are no cycles, and it's fully connected, it's a tree
    return true;
}

int main() {
    int m,n,u,v;
    cin>>n>>m;
    Graph graph = Graph();
    //Build the graph
    for(int edge=0; edge<m; edge++){
        cin>>u>>v;
        graph.addEdge(u,v);
    }
    if(dfs(graph,n)){
        cout<<"YES"<<endl;
    }
    else{
        cout<<"NO"<<endl;
    }
    return 0;
}

我試圖確定給定圖是否為樹。

我執行DFS並查找周期,如果檢測到周期,則給定的圖不是樹。

然后我檢查是否所有節點都已訪問過,如果沒有訪問過任何節點,則給定圖不是樹

輸入的第一行是:nm然后是m行,它們表示連接兩個節點的邊

n是節點數m是邊數

輸入示例:
3 2
1 2
2 3

這是一個SPOJ問題, 網址為http://www.spoj.com/problems/PT07Y/ ,我得到了錯誤的答案。 但是根據我的說法,DFS似乎是正確的。

因此,我針對注釋中的一些簡單測試用例檢查了您的代碼,看來對於

7 6
3 1
3 2
2 4
2 5
1 6
1 7

您的答案為“是”,而程序給出“否”。

在這種情況下,鄰居就是這樣:

1: 3 6 7 
2: 3 4 5 
3: 1 2 
4: 2 
5: 2 
6: 1 
7: 1 

所以,當你訪問1你推367堆棧。 您的父母被設置為1 一切都很好。

您從堆棧中彈出7 ,您不將任何內容壓入堆棧,並且清除了循環檢查,因此當您退出while循環時,您將visited[7]設置為true ,並將父級設置為7 (!!!!!)。

在這里,您可以看到運行不順利,因為從堆棧中彈出6后,您已將7保存為parent 它應該是1 這將使neighbor[0] != parent循環檢查失敗。

我建議在映射數組中添加保留父對象,並通過應用union-merge檢測周期。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM