LeetCode 1971[并查集 DFS BFS] 寻找图中是否存在路径 HERODING的LeetCode之路
Posted HERODING23
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LeetCode 1971[并查集 DFS BFS] 寻找图中是否存在路径 HERODING的LeetCode之路相关的知识,希望对你有一定的参考价值。
这道题是LeetCode中并查集标签下唯一一道简单题,是图论知识中最简单的问题,直接套用模板就可以得到结果,并查集、DFS、BFS都可以很好解决,首先给出DFS的解法。
DFS
第一步根据给定的边构建顶点邻接矩阵,定义访问数组,然后从source出发,不断往根据其相邻的边向下搜索,访问过的顶点标记为visited,直到找到destination返回true,否则返回false,代码如下:
class Solution
public:
bool validPath(int n, vector<vector<int>>& edges, int source, int destination)
// 构建邻接矩阵
vector<vector<int>> adj(n);
for(auto& edge : edges)
int x = edge[0], y = edge[1];
adj[x].emplace_back(y);
adj[y].emplace_back(x);
// 访问数组
vector<bool> visited(n, false);
return dfs(adj, source, destination, visited);
bool dfs(vector<vector<int>>& adj, int source, int destination, vector<bool>& visited)
if(source == destination)
return true;
visited[source] = true;
for(auto next : adj[source])
if(!visited[next] && dfs(adj, next, destination, visited))
return true;
return false;
;
BFS
这道题同样可以用广搜轻松解决,广搜的方法和深搜有异曲同工之妙,首先都是构造邻接矩阵和访问数组,接着从source出发,把所有与source相连接的边放入队列中,并标记为visited,如果遇到destination返回true,不断重复把队列中的顶点相连接的未被访问过的顶点放入到队列中,直到队列为空,返回false,代码如下:
class Solution
public:
bool validPath(int n, vector<vector<int>>& edges, int source, int destination)
// 构建邻接矩阵
vector<vector<int>> adj(n);
for(auto& edge : edges)
int x = edge[0], y = edge[1];
adj[x].emplace_back(y);
adj[y].emplace_back(x);
// 访问数组
vector<bool> visited(n, false);
queue<int> q;
q.push(source);
visited[source] = true;
while(!q.empty())
int node = q.front();
q.pop();
if(node == destination)
return true;
for(auto& next : adj[node])
if(!visited[next])
q.push(next);
visited[next] = true;
return false;
;
并查集
事实上,解决连通图问题,最便捷直接的方法还是并查集,并查集相当于一个通用的模板,因此可以封装成类,当需要使用的时候直接copy过来即可,当然直接编写也很简单,首先是定义两个数据结构,parent和rank数组,前者是记录每个节点的父标签,即所在图标签,rank是判断两图合并时到底是谁吞并谁,在本题中不起作用(谁吞谁都一样),以及定义三个函数,第一个构造函数,初始化parent和rank,每个节点初始都是一张图,所以初始parent就是本身,find函数是为了找到当前节点所在图的根节点,即图标签,connect函数是判断两个节点是否有相同的根节点,即是否在同一张图上,第三个函数是union函数,将两个图连接到一起,如果两个节点的根节点相同,则不要合并,不同的话,就把rank大的吞并rank小的图(直接修改被吞并图的parent[root]即可)。构造好并查集类后,对于本题来说简直手到擒来,直接实例化并查集类,遍历edges把点连通,然后判断source和destination是否在同一个图中,即返回uf.connect(source, destination)即可,代码如下:
class UnionFind
private:
vector<int> parent;
vector<int> rank;
public:
UnionFind(int n)
parent = vector<int>(n);
rank = vector<int>(n);
for(int i = 0; i < n; i ++)
parent[i] = i;
// 返回根节点标识
int find(int x)
if(parent[x] != x)
parent[x] = find(parent[x]);
return parent[x];
// 判断节点是否连接
bool connect(int x, int y)
return find(x) == find(y);
// 将两个连通图相连
void unionGraph(int x, int y)
int rootX = find(x);
int rootY = find(y);
if(rootX != rootY)
if(rank[rootX] > rank[rootY])
parent[rootY] = rootX;
else if(rank[rootX] > rank[rootY])
parent[rootX] = rootY;
else
parent[rootY] = rootX;
rank[rootX] ++;
;
class Solution
public:
bool validPath(int n, vector<vector<int>>& edges, int source, int destination)
UnionFind uf(n);
for(auto& edge : edges)
uf.unionGraph(edge[0], edge[1]);
return uf.connect(source, destination);
;
以上是关于LeetCode 1971[并查集 DFS BFS] 寻找图中是否存在路径 HERODING的LeetCode之路的主要内容,如果未能解决你的问题,请参考以下文章
2/10 并查集+bfs+dfs+最短路径+spfa队列优化
PAT Advanced 1034 Head of a Gang (30) [图的遍历,BFS,DFS,并查集]