每日LeetCode —— 2368. 受限条件下可到达节点的数目

229 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第14天,点击查看活动详情

题目描述

       给定一个由节点编号从0~n-1的n个节点组成的无向树,共有n-1条边,给定一个二维数组 edges 以及一个数组restricted,edges内存储边的信息,restricted中存储的是无法访问的节点编号。求在不访问restricted中的节点的情况下,从节点0开始可以到达的最多的节点数目。

例如110为特殊二进制序列,而100不是,因为其前缀码100的1数目小于0的数目。

例1:输入:n=8 edges=[[2,0],[3,0],[0,1],[6,1],[1,5],[2,7],[4,3]] restricted=[3]  输出:6

解释:该输入的树形结构如下图所示,由此可以看出,在不经过节点3的情况下,从0出发可以达到的节点有6个。

1.png

本题值得注意的地方:

  • 所给的边的信息没有顺序。

原题地址:2368. 受限条件下可到达节点的数目

解题思路

       利用map记录下所有节点的所有下一个节点,从0开始进行bfs,用队列来记录可以到达的节点的序号,为了避免走回头路,这里用一个标记map来记录节点的访问情况。这里为了方便判断一个节点是否是为受限节点,也用了一个map来记录节点的受限情况。

       每访问到一个节点,从记录中查询该节点的所有孩子节点,并试图将孩子节点入队,当一个节点要入队之前,检查该节点在此之前是否已经入队,即是否已经访问过,若没有则入队,并将结果res+1,表示可以到达的节点数+1。

实现代码

class Solution {
public:
    int reachableNodes(int n, vector<vector<int>>& edges, vector<int>& restricted) {
        // 记录已经节点的访问情况、节点访问受限的情况
        unordered_map<int,int> unmap1,unmap2;
        // 记录所能到达的节点数
        int ans=1;
        queue<int> qu;
        for(int tt=0;tt<restricted.size();tt++) unmap2[restricted[tt]]=1;
        // 记录每个节点的所有下一个节点编号信息
        map<int,vector<int>> map;
        for(int tt=0;tt<edges.size();tt++){
            if(unmap2.count(edges[tt][0])==0 && unmap2.count(edges[tt][1])==0){
                if(map.count(edges[tt][1])==0) map[edges[tt][1]]=vector<int>(0);
                if(map.count(edges[tt][0])==0) map[edges[tt][0]]=vector<int>(0);
                map[edges[tt][1]].push_back(edges[tt][0]);
                map[edges[tt][0]].push_back(edges[tt][1]);
            }
        }
        // 查找从0开始所能到达的节点数
        qu.push(0);
        unmap1[0]=1;
        while(qu.size()){
            int t=qu.front();
            auto vec=map[t];
            qu.pop();
            for(int i=0;i<vec.size();i++){
                // 如果该节点没有入队即被访问过,则将该节点入队
                if(unmap1.count(vec[i])==0){
                    ans++;
                    unmap1[vec[i]]=1;
                    qu.push(vec[i]);
                }
            }
        }
        return ans;
    }
};