题目来源:107. 寻找存在的路径
C++题解1:使用递归。对于找过的路径进行删除,避免陷入死循环。
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
void findpath(int source, int destination, vector<vector<int>> &grid, int &res){
if(source == destination) { //找到目的地
res = 1;
return;
}
int len = grid[source].size();
for(int i = len-1; i >= 0; i--) {//从后往前,方便删除路径
grid[source].pop_back(); // 递归中,对于找过的路径进行删除
findpath(grid[source][i], destination, grid, res);
if(res == 1) return;
}
return;
}
int main() {
int res = 0;
int N, M; cin>>N>>M;
vector<vector<int>> grid(N+1, vector<int>());
for(int i = 0; i < M; i++){
int a, b;
cin >> a >> b;
grid[a].push_back(b); // 添加路径,无向图
grid[b].push_back(a);
}
int source, destination;
cin >> source >> destination;
findpath(source, destination, grid, res);
cout << res<<endl;
return 0;
}
C++题解2(来源代码随想录):
并查集可以解决什么问题呢?
主要就是集合问题,两个节点在不在一个集合,也可以将两个节点添加到一个集合中。
并查集主要有三个功能:
- 寻找根节点,函数:find(int u),也就是判断这个节点的祖先节点是哪个
- 将两个节点接入到同一个集合,函数:join(int u, int v),将两个节点连在同一个根节点上
- 判断两个节点是否在同一个集合,函数:isSame(int u, int v),就是判断两个节点是不是同一个根节点
简单介绍并查集之后,我们再来看一下这道题目。
为什么说这道题目是并查集基础题目,题目中各个点是双向图链接,那么判断 一个顶点到另一个顶点有没有有效路径其实就是看这两个顶点是否在同一个集合里。
如何算是同一个集合呢,有边连在一起,就算是一个集合。
此时我们就可以直接套用并查集模板。
使用 join(int u, int v)将每条边加入到并查集。
最后 isSame(int u, int v) 判断是否是同一个根 就可以了。
#include <iostream>
#include <vector>
using namespace std;
int n; // 节点数量
vector<int> father = vector<int> (101, 0); // 按照节点大小定义数组大小
// 并查集初始化
void init() {
for (int i = 1; i <= n; i++) father[i] = i;
}
// 并查集里寻根的过程
int find(int u) {
return u == father[u] ? u : father[u] = find(father[u]);
}
// 判断 u 和 v是否找到同一个根
bool isSame(int u, int v) {
u = find(u);
v = find(v);
return u == v;
}
// 将v->u 这条边加入并查集
void join(int u, int v) {
u = find(u); // 寻找u的根
v = find(v); // 寻找v的根
if (u == v) return ; // 如果发现根相同,则说明在一个集合,不用两个节点相连直接返回
father[v] = u;
}
int main() {
int m, s, t, source, destination;
cin >> n >> m;
init();
while (m--) {
cin >> s >> t;
join(s, t);
}
cin >> source >> destination;
if (isSame(source, destination)) cout << 1 << endl;
else cout << 0 << endl;
}