2368. 受限条件下可到达节点的数目 【DFS、BFS、并查集】

16 阅读2分钟

2368. 受限条件下可到达节点的数目

BFS O(n)\lgroup O(n) \rgroup

class Solution:
    def reachableNodes(self, n: int, edges: List[List[int]], restricted: List[int]) -> int:

        r = set(restricted)
        g = [[] for _ in range(n)]
        for u, v in edges:
            if u not in r and v not in r:  # 都不受限 才连边
                g[u].append(v)
                g[v].append(u)

        res = 0
        q = deque([0])
        visited = set()  ## 不要忘了 visited
        while q:
            node = q.popleft()
            visited.add(node)
            res += 1
            for nxt in g[node]:
                if nxt not in visited:
                    q.append(nxt)
        return res 
class Solution {
public:
    int reachableNodes(int n, vector<vector<int>>& edges, vector<int>& restricted) {
        unordered_set<int> r(restricted.begin(), restricted.end());
        vector<vector<int>> g(n);
        for (auto e : edges){
            int u = e[0], v = e[1];
            if (!r.contains(u) && !r.contains(v)){
                g[u].emplace_back(v);
                g[v].emplace_back(u);
            }
        }

        queue<int> q{{0}};
        int res = 0;
        unordered_set<int> visited;
        visited.emplace(0);
        while (!q.empty()){
            int node = q.front(); q.pop();
            res += 1;
            for (int nxt : g[node]){
                if (!visited.contains(nxt)){
                    visited.emplace(nxt);
                    q.push(nxt);
                }
            }
        }
        return res;        
    }
};

DFS O(n)\lgroup O(n) \rgroup

class Solution:
    def reachableNodes(self, n: int, edges: List[List[int]], restricted: List[int]) -> int:

        r = set(restricted)
        g = [[] for _ in range(n)]
        for u, v in edges:
            if u not in r and v not in r:  # 都不受限 才连边
                g[u].append(v)
                g[v].append(u)

        def dfs(u, pa):
            cnt = 1
            for v in g[u]:
                if v != pa:
                    cnt += dfs(v, u)
            return cnt

        return dfs(0, -1) 
class Solution {
    vector<vector<int>> g;

    int dfs(int u, int pa){
        int cnt = 1;
        for (int v : g[u]){
            if (v != pa){
                cnt += dfs(v, u);
            }
        }
        return cnt;
    };

public:
    int reachableNodes(int n, vector<vector<int>>& edges, vector<int>& restricted) {
        unordered_set<int> r(restricted.begin(), restricted.end());
        g.resize(n); // 重要!!
        for (auto e : edges){
            int u = e[0], v = e[1];
            if (!r.contains(u) && !r.contains(v)){
                g[u].emplace_back(v);
                g[v].emplace_back(u);
            }
        }   
        return dfs(0, -1);
    }
};

image.png

class Solution {
public:
    int reachableNodes(int n, vector<vector<int>>& edges, vector<int>& restricted) {
        unordered_set<int> r(restricted.begin(), restricted.end());
        vector<vector<int>> g(n);
        for (auto e : edges){
            int u = e[0], v = e[1];
            if (!r.contains(u) && !r.contains(v)){
                g[u].emplace_back(v);
                g[v].emplace_back(u);
            }
        }  

        function<int(int, int)> dfs = [&] (int u, int pa){
            int cnt = 1;
            for (int v : g[u]){
                if (v != pa){
                    cnt += dfs(v, u);
                }
            }
            return cnt;
        };
        return dfs(0, -1);
    }
};

image.png

并查集 O(n×α(n))O(n)\lgroup O(n \times α(n))、 O(n) \rgroup

image.png

image.png

image.png

class UnionFind:
    def __init__(self, n): # 定义 parent 和 rank
        self.parent = list(range(n)) # 指向自己
        self.rank = [0] * n 

    def find(self, x):
        if self.parent[x] != x:
            self.parent[x] = self.find(self.parent[x])
        return self.parent[x]

    def union(self, x, y):
        rootx = self.find(x)
        rooty = self.find(y)
        if rootx != rooty:
            if self.rank[rootx] < self.rank[rooty]:
                self.parent[rootx] = rooty  # 指向 大的
            elif self.rank[rootx] > self.rank[rooty]:
                self.parent[rooty] = rootx 
            else:
                self.parent[rooty] = rootx  # 指向 前面那个
                self.rank[rootx] += 1

    def count(self):
        cnt = 0
        root0 = self.find(0)
        for i in range(len(self.parent)):
            if root0 == self.find(i): # parent 结点都为 0 的节点数
                cnt += 1
        return cnt 



class Solution:
    def reachableNodes(self, n: int, edges: List[List[int]], restricted: List[int]) -> int:
        r = set(restricted)

        uf = UnionFind(n)
        for u, v in edges:
            if u not in r and v not in r:
                uf.union(u, v)

        return uf.count()
class UnionFind{
public:
    UnionFind(int n) : parent(n), rank(n){
        for (int i = 1; i < n; ++i){
            parent[i] = i;
        }
    }

    int find(int x){
        if (parent[x] != x){
            x = find(parent[x]);
        }
        return parent[x];
    }

    void merge(int x, int y){// 这里不能用 union
        int rootx = find(x);
        int rooty = find(y);
        if (rootx != rooty){
            if (rank[rootx] > rank[rooty]){
                parent[rooty] = rootx;
            }else if (rank[rootx] < rank[rooty]){
                parent[rootx] = rooty;
            }else{
                parent[rooty] = rootx;
                ++rank[rootx];
            }
        }
    }

    int count(){
        int cnt = 0;
        int root0 = find(0);
        for (int i = 0; i < parent.size(); ++i){
            if (root0 == find(i)){
                cnt++;
            }
        }
        return cnt;
    }
private:
    vector<int> parent;
    vector<int> rank;
};

class Solution {
public:
    int reachableNodes(int n, vector<vector<int>>& edges, vector<int>& restricted) {
        unordered_set<int> r(restricted.begin(),restricted.end());

        UnionFind uf = UnionFind(n);
        for (auto e : edges){
            if  (!r.contains(e[0]) && !r.contains(e[1])){
                uf.merge(e[0], e[1]);
            }
        }
        return uf.count();        
    }
};