当前位置:   article > 正文

代码随想录刷题攻略---图论1-深搜1_图论深搜

图论深搜

例题1

所有可能的路径:给你一个有 n 个节点的 有向无环图(DAG),请你找出所有从节点 0 到节点 n-1 的路径并输出(不要求按特定顺序

 graph[i] 是一个从节点 i 可以访问的所有节点的列表(即从节点 i 到节点 graph[i][j]存在一条有向边)。

深搜三部曲

其实dfs的过程就是回溯算法的过程,框架是相通的

  1. void dfs(参数) {
  2. if (终止条件) {
  3. 存放结果;
  4. return;
  5. }
  6. for (选择:本节点所连接的其他节点) {
  7. 处理节点;
  8. dfs(图,选择的节点); // 递归
  9. 回溯,撤销处理结果
  10. }
  11. }

1.确定递归函数及参数

在该题中,递归函数的参数是graph二维数组当前结点x

2. 确定终止条件

终止条件是当目前搜索到的路径没有下一个能访问的结点时,将该路径结果存储。所以终止条件是该结点为graph数组的最后一个元素

3.处理目前搜索节点出发的路径

每一次搜索中,先找当前节点x的邻接点有哪些,故遍历该结点的邻接结点graph[x][i],在每一轮遍历中,将一个邻接点加入当前路径再以邻接点为当前结点x,继续深搜,进入下一层递归,当递归结束并保存了遍历路径时,再进行回溯,撤销本节点

code

  1. class Solution {
  2. public:
  3. vector<vector<int>> result;
  4. vector<int> path;
  5. vector<vector<int>> allPathsSourceTarget(vector<vector<int>>& graph) {
  6. path.push_back(0);
  7. dfs(graph,0);//当前结点是0
  8. return result;
  9. }
  10. void dfs(vector<vector<int>>& graph,int x)
  11. {
  12. //找出所有从节点 0 到节点 n-1 的路径,故graph.size()-1为结点个数
  13. if(x == graph.size()-1)
  14. {
  15. result.push_back(path);
  16. return ;
  17. }
  18. for(int i=0 ;i < graph[x].size() ; i++)
  19. {
  20. path.push_back(graph[x][i]);
  21. dfs(graph,graph[x][i]);
  22. path.pop_back();
  23. }
  24. }
  25. };

例题2

给你一个由 '1'(陆地)和 '0'(水)组成的的二维网格,请你计算网格中岛屿的数量。

岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。

此外,你可以假设该网格的四条边均被水包围。

深搜三部曲

1.确定递归函数及参数

在该题中,递归函数的参数是graph二维数组/当前结点x,y/是否访问过数组visted

2. 确定终止条件

处理函数numIslands中,我们对没有访问过的陆地结点先进行计数,每计数一次,则把该结点的连通节点全部标为ture,即已访问过。在后续的计数过程中不计入这些连通结点。终止条件是当目前搜索到的路径没有下一个能访问的结点时(即当前节点已经访问过或者当前节点是海洋而不是陆地)

3.处理目前搜索节点出发的路径

每一次搜索中,先访问结点(x,y)并将对应的visited数据元素置为true,然后深度搜索该结点的的正下方结点,再将该结点变为当前结点x,置为true后继续深搜,进入下一层递归,当递归结束后,再搜索当前结点的右/上/左边的结点并分别深搜。

code

  1. class Solution {
  2. public:
  3. int dir[4][2] = {0, 1, 1, 0, -1, 0, 0, -1}; // 四个方向
  4. int numIslands(vector<vector<char>>& grid) {
  5. int n = grid.size(), m = grid[0].size();
  6. vector<vector<char>> visited(n,vector<char>(m,false));//是否已访问过
  7. int res = 0;//岛屿数量
  8. for(int i=0; i<n; i++)
  9. for(int j=0; j<m; j++)
  10. {
  11. if(!visited[i][j] && grid[i][j] == '1')//未访问过而且是陆地不是海
  12. {
  13. res++;//岛屿数量加一
  14. dfs(grid,visited,i,j);//将这块陆地的邻接陆地全标为true,不参与下次的遍历
  15. }
  16. }
  17. return res;
  18. }
  19. void dfs(vector<vector<char>>& grid,vector<vector<char>>& visited,int x,int y)
  20. {
  21. //深度遍历 x,y 结点的邻接点,将这些节点设为 访问过
  22. if(grid[x][y] == '0' || visited[x][y])//访问过此节点或碰到海水
  23. return;
  24. visited[x][y] = true;
  25. for(int i = 0; i < 4; i++)
  26. {
  27. int nextx = x + dir[i][0];
  28. int nexty = y + dir[i][1];
  29. if(nextx < 0 || nextx >= grid.size() || nexty < 0 || nexty >= grid[0].size())
  30. continue;//越界,查看往其他地方走能不能行
  31. dfs(grid,visited,nextx,nexty);
  32. }
  33. }
  34. };

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/618857
推荐阅读
相关标签
  

闽ICP备14008679号