题目链接:力扣
题目描述
节点间通路。给定有向图,设计一个算法,找出两个节点之间是否存在一条路径。
示例1:
输入:n = 3, graph = [[0, 1], [0, 2], [1, 2], [1, 2]], start = 0, target = 2
输出:true
示例2:输入:n = 5, graph = [[0, 1], [0, 2], [0, 4], [0, 4], [0, 1], [1, 3], [1, 4], [1, 3], [2, 3], [3, 4]], start = 0, target = 4
输出 true
提示:节点数量n在[0, 1e5]范围内。
节点编号大于等于 0 小于 n。
图中可能存在自环和平行边。
果果念
又是涨知识的一天(不是,补算法中....)。今天下午上了高级算法课,讲到了DFS和BFS,今天晚上刷了一道leetcode题目,本来想多刷几道呢,无奈快乐的时光美好而又短暂(不是,自己太菜了...),下面分享一下这道题目。
还没有遇到过一些面试或者机试考图论的,但是基础的深搜和广搜应该是需要掌握的,我发现自己的基础太差了,这几天也不敢投简历了。上次的堆排序和快速排序今天又看了一下,也敲了一下,多多思考,会有收益哒。
关于这道题目,就是一个很经典的深搜题目,广搜应该也可以做吧。主要说一下两点:
- 第一点:关于集合,我还是第一次使用stl中的集合,unordered_set,集合中的性质就是不可以插入同样的元素,也就是唯一性。因为这道题目是有向图,而且还可能存在平行边,因此,这里使用vector<unordered_set<int>> edge,edge.resize(n),建立边。
- 第二点:标记数组,这个标记数组的作用是为了避免环,这里也使用了STL自带的unordered_set<int> visted,利用visted.count(v)>0判断v是否已经被访问过,也就是这个集合是否包含v,visted.insert(v),访问v。
拓:我利用了队列记录了访问的顺序,嘻嘻。
unordered_set:元素内部没有排序,基于哈希表;
set:基于红黑树实现,有序的。
刚刚喝了一杯真果粒,不是广告,好开心啊。
代码
class Solution {
public:
vector<unordered_set<int>> edge;//边
unordered_set<int> visited;//标记数组,标记走过的顶点
queue<int> path;//标记路径
bool dfs(int start, int target){
//已经走过这个定点了,别尝试了,我的宝
// cout<<visited.count(start)<<endl;
if(visited.count(start)){
return false;
}
//我的宝儿,你成功了
if(start==target) return true;
visited.insert(start);
for(auto &v:edge[start]){
//我的宝儿,有一个走通,就代表存在通路呀
path.push(v);
if(dfs(v,target)){
return true;
}
path.pop();
}
return false;
}
bool findWhetherExistsPath(int n, vector<vector<int>>& graph, int start, int target) {
//节点编号 0~4
edge.resize(n);//n个顶点
for(auto &e:graph){
edge[e[0]].insert(e[1]);//去掉平行边
}
bool ans=dfs(start,target);
// cout<<path.size()<<endl;
while(path.empty()!=true){
// cout<<path.front()<<endl;
path.pop();
}
return ans;
}
};