尋找是否存在從source到destination的路徑

七块蛋糕發表於2024-04-21

The Find if Path Exists in Graph problem involves determining whether there is a path between two given nodes (source and destination) in an undirected graph. The graph is represented by n nodes and a list of edges, where each edge specifies a connection between two nodes.

Given:

n: Number of nodes in the graph.
edges: List of edges where each edge is represented as [u, v], indicating an undirected edge between node u and node v.
source: The starting node for the path.
destination: The target node to reach.

Objective:
You need to implement a solution that can determine if there exists a path from the source node to the destination node in the given graph.

Output:
Return True if there exists a path from source to destination, otherwise return False.

解題:

  1. 重構給出的圖結構
    題目給出的是一對對二維陣列(向量表)edges,用來表示圖中所有的邊。
    重構:從已有的二維陣列中構建一個鄰接表,這會讓之後遍歷每一個節點和它的相鄰節點變得高效。

  2. DFS函式的邏輯:
    1.)我們需要一個集合visited來儲存每次迴圈訪問過的節點,每次只要是訪問過的節點,都把它放到visite集合中。
    2.) 構建一個遞迴函式,從source節點開始,首先判斷這個source是不是就是要找的destination,如果是則返回true,否則找到和source相連線的所有鄰節點,選擇其中一個並判斷:這個節點有沒有被遍歷過(是否在visited中能找到),如果沒有,則選中它作為遞迴的起點,把它作為新的source遞迴呼叫這個函式,重複以上的操作。
    3.)透過遞迴可以充分遍歷完圖中的所有節點,如果最終沒有找到預先給定的destination,則表示不存在從source到destination的路徑,返回false.

class Solution {
public:
    bool validPath(int n, vector<vector<int>>& edges, int source, int destination) {
        unordered_map<int, vector<int>> graph;

        for (const auto &edge: edges) {
            int u = edge[0];
            **int v = edge[1];

            graph[u].push_back(v);
            graph[v].push_back(u);
        }

        unordered_set<int> visited;
        return dfs(source, destination, graph, visited);
    }


    bool dfs(int node, int destination, unordered_map<int, vect**or<int>> &graph, unordered_set<int> &visited) {
        if (node == destination) {**
            return true;
        }

        visited.insert(node);
        for (int neighbor: graph[node]) {
            if (visited.find(neighbor) == visited.end()) {
                if (dfs(neighbor, destination, graph, visited)) {
                    return true;
                }
            }
        }
        return false;
    }
};
  1. 首先也是和方法一一樣重構圖結構。
  2. BFS函式邏輯:
    1.)同樣需要建立一個集合visited用來儲存訪問過的節點,以保證遍歷的過程中迴圈的有界性以及避免重複訪問同一個節點。
    2.)這次用一個while迴圈替代遞迴,對於while,需要創造一個結束的邊界條件:使用queue容器並判斷queue容器是否為空,為空則停止迴圈。具體操作:把關注的那個節點(沒有被訪問過的)放入佇列queue中,進入迴圈while判斷,把這個節點pop出去,並把這個節點儲存到visted集合內。找到和當前節點相鄰的同時未被訪問過的一個新節點,把它作為新關注的節點並放到佇列中,進入下一輪while迴圈,確定這個節點是否等於destination,如果等於則結束迴圈,否則找一個與該節點相鄰的下一個鄰接點重複迴圈,如果最後queue在進行while判斷時為空,那麼迴圈終止,表示遍歷完所有節點,沒有找到從source到destination的路徑。
class Solution {
public:
    bool validPath(int n, vector<vector<int>>& edges, int source, int destination) {
       unordered_map<int, vector<int>> graph;

       for (const auto &edge: edges) {
        int u = edge[0];
        int v = edge[1];
        graph[u].push_back(v);
        graph[v].push_back(u);
       }

       queue<int> queue;
       unordered_set<int> visited;

       queue.push(source);
       visited.insert(source);

       while (!queue.empty()) {
        int node = queue.front();
        queue.pop();

        if (node == destination) {
            return true;
        }

        for (int neighbor: graph[node]) {
            if (visited.find(neighbor) == visited.end()) {
                visited.insert(neighbor);
                queue.push(neighbor);
            }
        }

       }
       return false;
    }
};

相關文章