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

463.岛屿的周长

分析:
  • 1.陆地的旁边是海面,存在周长
  • 2.陆地在边界上,存在周长
思路一:深度优先遍历
  • 1.通过记录访问情况来访问数据
cpp 复制代码
class Solution {
public:
    int direct[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
    int res=0;
    void dfs(vector<vector<int>>&grid,vector<vector<bool>>&visted,int x,int y){
        for(int i=0;i<4;i++){
            int nextx=x+direct[i][0];
            int nexty=y+direct[i][1];
            if(nextx>=0 && nextx<grid.size() && nexty>=0 && nexty<grid[0].size()){
                if(!visted[nextx][nexty]){
                    if(grid[nextx][nexty]==0) res++;//那一边是海面
                    else{
                        visted[nextx][nexty]=true;
                        dfs(grid,visted,nextx,nexty);
                    }
                }
            }
            else res++;//那一边是边界
        }
    }
    int islandPerimeter(vector<vector<int>>& grid) {
        int n=grid.size(),m=grid[0].size();
        vector<vector<bool>>visted(n,vector<bool>(m,false));
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                if(!visted[i][j] && grid[i][j]==1){
                    visted[i][j]=true;
                    dfs(grid,visted,i,j);
                }
            }
        }
        return res;
    }
};

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

分析:
  • 寻找两个节点间是否存在路径,就是寻找两个节点是否在同一集合中
思路一:并查集
  • 1.初始化集合
  • 2.把各个节点进行连接
  • 3.寻根判断
cpp 复制代码
class Solution {
public:
    int n=200005;
    vector<int>father=vector<int>(n,0);
    void init(){//并查集初始化
        for(int i=0;i<n;i++) father[i]=i;
    }
    int find(int u){//并查集寻根
        return u==father[u]?u:father[u]=find(father[u]);
    }
    bool isSame(int u,int v){
        u=find(u);
        v=find(v);
        return u==v;
    }
    void join(int u,int v){//连接两个节点
        u=find(u);
        v=find(v);
        if(u==v) return;//说明已经存在连接
        father[u]=v;//进行连接
    }
    bool validPath(int n, vector<vector<int>>& edges, int source, int destination) {
        init();
        for(int i=0;i<edges.size();i++) join(edges[i][0],edges[i][1]);//连接节点
        return isSame(source,destination);//寻根判断
    }
};

684.冗余连接

分析:
  • 1.出现两个节点在同一集合,即有冗余
思路一:并查集
  • 1.初始化
  • 2.边添加边判断
cpp 复制代码
class Solution {
public:
    vector<int>father=vector<int>(1001,0);
    void init(){
        for(int i=0;i<1001;i++) father[i]=i;
    }
    int find(int u){//寻根
        return u==father[u]?u:father[u]=find(father[u]);
    }
    bool isSame(int u,int v){//判断是否同一集合
        u=find(u);
        v=find(v);
        if(u==0 && v==0) return false;
        return u==v;
    }
    void join(int u,int v){//连接节点
        u=find(u);
        v=find(v);
        if(u==v) return;
        father[u]=v;
    }
    vector<int> findRedundantConnection(vector<vector<int>>& edges) {
        init();//初始化!!!
        int n=edges.size();
        for(int i=0;i<n;i++){
            if(isSame(edges[i][0],edges[i][1])) return edges[i];//出现两个节点在同一集合
            else join(edges[i][0],edges[i][1]);
        }
        return vector<int>();
    }
};

685.冗余连接 ||

分析:
  • 只存在一条冗余边,有三种情况:
  • 1.入度可以通过遍历获取
  • 2.环可以通过判断两节点是否在同一集合获取
思路一:并查集
  • 1.先获取所有节点的入度
  • 2.存在节点入度为2:
    • 倒序找出入度为 2 的节点边
    • 节点边不考虑时,判断图是否为树
  • 3.不存在节点入度为2:
    • 判断删除那一条边存在环,直接返回
cpp 复制代码
class Solution {
public:
    static const int N=1010;
    int father[N];
    int n;
    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]);
    }
    bool same(int u,int v){//判断是否在同一集合
        u=find(u);
        v=find(v);
        return u==v;
    }
    void join(int u,int v){//连接两个节点
        u=find(u);
        v=find(v);
        if(u==v) return;
        father[u]=v;
    }
    vector<int> getMoveEdge(const vector<vector<int>>&edges){//获取要删除的冗余边
        init();
        for(int i=0;i<n;i++){
            if(same(edges[i][0],edges[i][1])) return edges[i];//已经存在同一集合,所以此线冗余
            join(edges[i][0],edges[i][1]);
        }
        return {};//不存在冗余
    }
    bool judge(const vector<vector<int>>&edges,int deleteEdge){//判断删除该边是否是树
        init();
        for(int i=0;i<n;i++){
            if(i==deleteEdge) continue;//删除就不考虑
            if(same(edges[i][0],edges[i][1])) return false;//仍然存在同一集合,绝对不是树
            join(edges[i][0],edges[i][1]);
        }
        return true;
    }

    vector<int> findRedundantDirectedConnection(vector<vector<int>>& edges) {
        n=edges.size();
        int inDegree[N]={0};
        vector<int>mid;
        for(int i=0;i<n;i++) inDegree[edges[i][1]]++;//记录入度
        for(int i=n-1;i>=0;i--){//从右侧开始记录
            if(inDegree[edges[i][1]]==2) mid.push_back(i);//记录入度为2的节点的下标
        }
        if(mid.size()>0){//存在入度为2的节点
            if(judge(edges,mid[0])) return edges[mid[0]];//最右边的边不考虑,图为树
            else return edges[mid[1]];
        }
        return getMoveEdge(edges);
    }
};
相关推荐
phoenix@Capricornus1 小时前
反向传播算法——矩阵形式递推公式——ReLU传递函数
算法·机器学习·矩阵
Inverse1621 小时前
C语言_动态内存管理
c语言·数据结构·算法
数据与人工智能律师1 小时前
虚拟主播肖像权保护,数字时代的法律博弈
大数据·网络·人工智能·算法·区块链
wuqingshun3141592 小时前
蓝桥杯 16. 外卖店优先级
c++·算法·职场和发展·蓝桥杯·深度优先
YouQian7722 小时前
2025春训第十九场
算法
CodeJourney.2 小时前
基于MATLAB的生物量数据拟合模型研究
人工智能·爬虫·算法·matlab·信息可视化
Epiphany.5562 小时前
素数筛(欧拉筛算法)
c++·算法·图论
爱吃涮毛肚的肥肥(暂时吃不了版)3 小时前
项目班——0510——JSON网络封装
c++·算法·json
liang_20263 小时前
【HT周赛】T3.二维平面 题解(分块:矩形chkmax,求矩形和)
数据结构·笔记·学习·算法·平面·总结
緈福的街口3 小时前
【leetcode】2900. 最长相邻不相等子序列 I
算法·leetcode·职场和发展