• day-65 代码随想录算法训练营(19)图论 part 04


    463.岛屿的周长

    分析:
    • 1.陆地的旁边是海面,存在周长
    • 2.陆地在边界上,存在周长
    思路一:深度优先遍历
    • 1.通过记录访问情况来访问数据
    1. class Solution {
    2. public:
    3. int direct[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
    4. int res=0;
    5. void dfs(vectorint>>&grid,vectorbool>>&visted,int x,int y){
    6. for(int i=0;i<4;i++){
    7. int nextx=x+direct[i][0];
    8. int nexty=y+direct[i][1];
    9. if(nextx>=0 && nextxsize() && nexty>=0 && nexty0].size()){
    10. if(!visted[nextx][nexty]){
    11. if(grid[nextx][nexty]==0) res++;//那一边是海面
    12. else{
    13. visted[nextx][nexty]=true;
    14. dfs(grid,visted,nextx,nexty);
    15. }
    16. }
    17. }
    18. else res++;//那一边是边界
    19. }
    20. }
    21. int islandPerimeter(vectorint>>& grid) {
    22. int n=grid.size(),m=grid[0].size();
    23. vectorbool>>visted(n,vector<bool>(m,false));
    24. for(int i=0;i
    25. for(int j=0;j
    26. if(!visted[i][j] && grid[i][j]==1){
    27. visted[i][j]=true;
    28. dfs(grid,visted,i,j);
    29. }
    30. }
    31. }
    32. return res;
    33. }
    34. };

    1971.寻找图中是否存在路径

    分析:
    • 寻找两个节点间是否存在路径,就是寻找两个节点是否在同一集合中
    思路一:并查集
    • 1.初始化集合
    • 2.把各个节点进行连接
    • 3.寻根判断
    1. class Solution {
    2. public:
    3. int n=200005;
    4. vector<int>father=vector<int>(n,0);
    5. void init(){//并查集初始化
    6. for(int i=0;i
    7. }
    8. int find(int u){//并查集寻根
    9. return u==father[u]?u:father[u]=find(father[u]);
    10. }
    11. bool isSame(int u,int v){
    12. u=find(u);
    13. v=find(v);
    14. return u==v;
    15. }
    16. void join(int u,int v){//连接两个节点
    17. u=find(u);
    18. v=find(v);
    19. if(u==v) return;//说明已经存在连接
    20. father[u]=v;//进行连接
    21. }
    22. bool validPath(int n, vectorint>>& edges, int source, int destination) {
    23. init();
    24. for(int i=0;isize();i++) join(edges[i][0],edges[i][1]);//连接节点
    25. return isSame(source,destination);//寻根判断
    26. }
    27. };

    684.冗余连接

    分析:
    • 1.出现两个节点在同一集合,即有冗余
    思路一:并查集
    • 1.初始化
    • 2.边添加边判断
    1. class Solution {
    2. public:
    3. vector<int>father=vector<int>(1001,0);
    4. void init(){
    5. for(int i=0;i<1001;i++) father[i]=i;
    6. }
    7. int find(int u){//寻根
    8. return u==father[u]?u:father[u]=find(father[u]);
    9. }
    10. bool isSame(int u,int v){//判断是否同一集合
    11. u=find(u);
    12. v=find(v);
    13. if(u==0 && v==0) return false;
    14. return u==v;
    15. }
    16. void join(int u,int v){//连接节点
    17. u=find(u);
    18. v=find(v);
    19. if(u==v) return;
    20. father[u]=v;
    21. }
    22. vector<int> findRedundantConnection(vectorint>>& edges) {
    23. init();//初始化!!!
    24. int n=edges.size();
    25. for(int i=0;i
    26. if(isSame(edges[i][0],edges[i][1])) return edges[i];//出现两个节点在同一集合
    27. else join(edges[i][0],edges[i][1]);
    28. }
    29. return vector<int>();
    30. }
    31. };

    685.冗余连接 || 

    分析:
    • 只存在一条冗余边,有三种情况:

    • 1.入度可以通过遍历获取
    • 2.环可以通过判断两节点是否在同一集合获取 
    思路一:并查集
    • 1.先获取所有节点的入度
    • 2.存在节点入度为2:
      • 倒序找出入度为 2 的节点边
      • 节点边不考虑时,判断图是否为树
    • 3.不存在节点入度为2:
      • 判断删除那一条边存在环,直接返回
    1. class Solution {
    2. public:
    3. static const int N=1010;
    4. int father[N];
    5. int n;
    6. void init(){//初始化
    7. for(int i=1;i<=n;++i) father[i]=i;
    8. }
    9. int find(int u){//寻根
    10. return u==father[u]?u:father[u]=find(father[u]);
    11. }
    12. bool same(int u,int v){//判断是否在同一集合
    13. u=find(u);
    14. v=find(v);
    15. return u==v;
    16. }
    17. void join(int u,int v){//连接两个节点
    18. u=find(u);
    19. v=find(v);
    20. if(u==v) return;
    21. father[u]=v;
    22. }
    23. vector<int> getMoveEdge(const vectorint>>&edges){//获取要删除的冗余边
    24. init();
    25. for(int i=0;i
    26. if(same(edges[i][0],edges[i][1])) return edges[i];//已经存在同一集合,所以此线冗余
    27. join(edges[i][0],edges[i][1]);
    28. }
    29. return {};//不存在冗余
    30. }
    31. bool judge(const vectorint>>&edges,int deleteEdge){//判断删除该边是否是树
    32. init();
    33. for(int i=0;i
    34. if(i==deleteEdge) continue;//删除就不考虑
    35. if(same(edges[i][0],edges[i][1])) return false;//仍然存在同一集合,绝对不是树
    36. join(edges[i][0],edges[i][1]);
    37. }
    38. return true;
    39. }
    40. vector<int> findRedundantDirectedConnection(vectorint>>& edges) {
    41. n=edges.size();
    42. int inDegree[N]={0};
    43. vector<int>mid;
    44. for(int i=0;i1]]++;//记录入度
    45. for(int i=n-1;i>=0;i--){//从右侧开始记录
    46. if(inDegree[edges[i][1]]==2) mid.push_back(i);//记录入度为2的节点的下标
    47. }
    48. if(mid.size()>0){//存在入度为2的节点
    49. if(judge(edges,mid[0])) return edges[mid[0]];//最右边的边不考虑,图为树
    50. else return edges[mid[1]];
    51. }
    52. return getMoveEdge(edges);
    53. }
    54. };

  • 相关阅读:
    【博客551】实现主备高可用vip的几种方式
    湖仓一体电商项目(十一):编写写入DWS层业务代码
    【Docker镜像】Node.js项目之使用Dockerfile构建镜像
    CSS3_媒体查询
    用JS实现简单的新闻向上轮播效果
    【9.28】刷题
    blazor调试部署全过程
    java常见的设置模式(下)
    p18 线性代数,行阶梯型矩阵
    hack the box-blue team
  • 原文地址:https://blog.csdn.net/Ricardo_XIAOHAO/article/details/133576158