携手创作,共同成长!这是我参与「掘金日新计划 · 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个。
本题值得注意的地方:
- 所给的边的信息没有顺序。
原题地址: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;
}
};