LeetCode 261. Graph Valid Tree Detect Cycle In Directed/Undirected Graph

DFS

https://www.geeksforgeeks.org/check-given-graph-tree/

判断一个Graph是否为Tree有两个条件:1) 连通图  2) 没有环

这道题是无向图,判断有没有环可以dfs来做,比有向图容易很多。

dfs判断图是否有环:Detect Cycle In Directed/Undirected Graph

判断是否是连通图很容易,在dfs一个node后,只要看看是不是所有节点都visit过了即可。

也可以用图论的知识,对于Tree,|E| = |V|-1

时间复杂度 O(V+E)

class Solution {
public:
    vector<list<int>> adj;
    
    bool validTree(int n, vector<vector<int>>& edges) {
        adj.resize(n,list<int>());
        for (auto edge:edges){
            int u=edge[0], v=edge[1];
            adj[u].push_back(v);
            adj[v].push_back(u);
        }
        vector<bool> visited(n,false);
        if (dfs(0,visited,-1)) return false;
        for (bool x:visited){
            if (x==false) return false;
        }
        return true;
    }
    
    bool dfs(int i, vector<bool> &visited, int parent){ // return if has cycle
        visited[i] = true;
        for (auto x:adj[i]){
            if (visited[x] && x!=parent) return true;
            if (!visited[x]){
                if (dfs(x,visited,i))
                    return true;
            }
        }
        return false;
    }
};

Union Find 

https://www.geeksforgeeks.org/union-find-algorithm-set-2-union-by-rank/

用uniond find来做也是可以的,而且更加直观。由于节点0~n-1,可以用一个parent数组来做。

数组来做的话用size来判断如何union比较简单,用parent[root]=-size即可。

时间复杂度比较复杂,如果没有path compression,union和find都需要logV,所以总的复杂度为ElogV。

加上path compression后,union和find 都是 amortized O(1)。

class Solution {
public:
    vector<int> parent;
    
    bool validTree(int n, vector<vector<int>>& edges) {
        if (edges.size()!=n-1) return false;
        
        parent.resize(n,-1);
        for (auto edge:edges){
            int u=edge[0], v=edge[1];
            int root1=Find(u), root2=Find(v);
            if (root1==root2) return false;
            
            // whoever's size is bigger becomes parent of other
            // notice parent[root] is negative, if parent[root] is smaller, then its size is larger
            if (root1>root2){
                parent[root2] += parent[root1];
                parent[root1] = root2;
            }else{
                parent[root1] += parent[root2];
                parent[root2] = root1;
            }
        }
        return true;
    }
    
    int Find(int x){
        if (parent[x]<0) return x;
        return parent[x]=Find(parent[x]);
    }
};

猜你喜欢

转载自www.cnblogs.com/hankunyan/p/10965551.html