一道题练三种算法(并查集/BFS/DFS)

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

1.并查集

将给定双向图中的连通分量看成一个集合,把所有相连节点合并为一个集合,最后直接查找start和end节点的祖宗节点,若在同一集合内则说明存在从顶点start到end的路径

class Solution {
public:
    static const int maxn=1e5;
    int *fa=new int[maxn*2+10];
    int find(int x){
        if(fa[x]==x)return x;
        else fa[x]=find(fa[x]);//这一步是重点!!!
        return fa[x];
    }
    void merge(int i,int j){
        int fa_i=find(i);
        int fa_j=find(j);
        fa[fa_i]=fa_j;
    }
    bool validPath(int n, vector<vector<int>>& edges, int source, int destination) {
        
        for(int i=0;i<n;++i)fa[i]=i;
        
        for(int i=0;i<edges.size();++i){
            //for(int j=0;j<edges[i].size();++j){
                merge(edges[i][0],edges[i][1]);
            //}
        }
        int fa_i=find(source);
        int fa_j=find(destination);
        //fa[fa_i]=fa_j;
        if(fa_j==fa_i)return 1;
        return 0;
    }
};

2.BFS(其实就是走迷宫的做法),时间复杂度O(N)

注意不要一开始就将vector初始化为n*n大小,这样会导致在执行队列内的代码:寻找当前节点的相邻节点的时间复杂度大大增加。

vector<int>v(n)和vector<int>v[n]区别:(n)表示开辟了n个空间,[n]表示创建了n个容器,二维的vector类似

class Solution {
public:
    vector<int>vis;
    bool validPath(int n, vector<vector<int>>& edges, int source, int destination) {
        if(edges.empty())return 1;
        int len=edges.size();
        vector<vector<int>>mp(n);
        //vector<vector<int>>vis(n,vector<int>(n,0));
        vis.resize(n);
        
        for(int i=0;i<edges.size();++i){
            mp[edges[i][0]].push_back(edges[i][1]);
            mp[edges[i][1]].push_back(edges[i][0]);
        }
        queue<int>q;
        q.push(source);
        //vis[source]=1;
        while(!q.empty()){
            int now=q.front();q.pop();
            vis[now]=1;
            if(now==destination)return 1;
            for(int i=0;i<mp[now].size();++i){
                if(vis[mp[now][i]]==0){
                    q.push(mp[now][i]);
                }
            }
        }
        return 0;
    }
};

3.DFS

class Solution {
public:
    vector<int>vis;
    int flag=0;
    void dfs(vector<vector<int>>& mp, int start, int end){
        
        if(start==end){
            flag=1;
            return;
        }
        vis[start]=1;
        for(int i=0;i<mp[start].size();++i){
            if(!vis[mp[start][i]]){
                dfs(mp,mp[start][i],end);
            }
        }
        //return 0;
    }
    bool validPath(int n, vector<vector<int>>& edges, int source, int destination) {
        if(edges.empty())return 1;
        vector<vector<int>>mp(n);
        vis.resize(n);
        
        for(int i=0;i<edges.size();++i){
            mp[edges[i][0]].push_back(edges[i][1]);
            mp[edges[i][1]].push_back(edges[i][0]);
        }
        dfs(mp,source,destination);
        if(flag)return 1;
        return 0;
    }
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值