【DFS】广联达2023秋招-迷宫(dfs树的遍历和回溯)
https://oj.algomooc.com/problem.php?id=6100
小明在梦中困在一个迷宫里了。迷宫太难了,小明发动特殊能力让迷宫变得简单起来。迷宫变成了一张有n个节点的有根树(根为1号节点)的结构,只能在一个节点往其儿子节点走,而当没有导向其他节点的路径存在时,即该节点没有儿子节点时,便走出了迷宫。这样一来,小明只要沿着任意可以走的路径行进就肯定可以到达出口了!
出发前为了做好周密准备,小明想知道处于这个迷宫的各个位置能到哪些出口。
输入
第一行3个整数分别为\(n,m和q\)表示迷宫节点数量,迷宫路径数量和询问数量。
第二行m个整数\(u_1, u_2, ..., u_m\)
第三行m个整数\(v_1, v_2, ..., v_m\)
其中\(u_i, v_i\)代表第i条有向路径为从节点\(u_i\)通往节点\(v_i\),即节点\(u_i\)有一个儿子节点\(v_i\)。保证形成一棵以1号节点为根的有根树。
第四行\(q\)个整数\(a_1, a_2, ..., a_q\)。表示第\(i\)次询问为:若处于\(a_i\)节点,可能到达多少个不同的出口?注意,若一个节点没有导向其他节点的路径存在时,即没有儿子节点时,这个节点则为一个出口。
\(1 <= n, m, q <= 50000, 1 <= u_i, v_i <= n, u_i != v_i\)
输出
输出一行q个整数,分别表示每次询问的答案。
样例输入
3 2 3
1 1
2 3
1 2 3
样例输出
2 1 1
这个就是一个dfs,首先我们考虑这个树的根肯定是1,然后那么倒数第二层(和根直接相连的节点)它的答案就是跟他直接相连的根的个数。我们在回溯的时候就让倒数第二层那个根的答案加上和他之间相连的根的答案就行,所以:令ans[u]为以u为根节点的子树中的叶子节点的数目,显然\(ans[u] = ans[v_1] + ans[v_2] + ans[v_k],其中v_1, v_2, ..., v_k为u的所有的子节点\)。而当u没有节点时,ans[u] = 1。我们只需要在回溯的时候处理一下就行
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
const int maxn=1e5+100;
vector<int>e[maxn];
int n,m,q;
int a[maxn];
int ans[maxn];
void dfs(int u,int fa){
if(e[u].size()==1){
ans[u]=1;
}
else{
ans[u]=0;
}
for(int i=0;i<e[u].size();i++){
int v=e[u][i];
if(fa!=v){
dfs(v,u);
ans[u]+=ans[v];
}
}
}
int main(){
cin>>n>>m>>q;
for(int i=1;i<=m;i++){
cin>>a[i];
}
for(int i=1;i<=m;i++){
int v;
cin>>v;
e[a[i]].push_back(v);
e[v].push_back(a[i]);
}
dfs(1,-1);
while(q--){
int x;
cin>>x;
cout<<ans[x]<<endl;
}
}

浙公网安备 33010602011771号