题意:
一棵以1为根的树,树上有些点是红的。一个叶子是合法的当且仅当从根到它的路径上出现的连续红点个数不超过m。求有多少个叶子是合法的。
Input
第一行两个整数n和m(2≤n ≤105,1≤m≤n)
第二行n个整数0或1,如果是1,表示第i个点是红点。
接下来n-1行,每行两个整数x和y,表示树上的一条边。
Output
输出满足条件的叶子节点数
解析:树(图)的dfs,其中树的构建使用邻接表(树就是图,本蒟蒻一开始竟然卡在了不会建树上。。。丢脸),每次dfs时,连续节点++,如果不连续,就赋值为0。然后每次dfs时要比较连续节点数与m的大小关系,如果连续节点>m,说明此路不通,返回0;如果成功的走到叶子节点,说明存在一条可行路,返回1。
代码如下:
#include<iostream>
#include<algorithm>
#include<string.h>
#include<vector>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
ll a[maxn];
int n,m;
vector<ll>vec[maxn];
int cnt=0;
bool vis[maxn];
int dfs(int t,int cnt)
{
if(a[t])//如果为红色,当前节点数++
cnt++;
else
cnt=0;//否则当前节点数重设为0
if(cnt>m||vis[t])return 0;//如果节点个数>m或已经访问过,说明此路不能走,路的个数为0
int ans=0;
vis[t]=1;
if(t>1&&vec[t].size()==1)return 1;//如果走到头了,说明存在一条路
for(int i=0;i<vec[t].size();i++){
int w=vec[t][i];
ans+=dfs(w,cnt);
}
return ans;
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>a[i];
}
int a,b;
memset(vis,0,sizeof(vis));
for(int i=1;i<=n-1;i++){
cin>>a>>b;
vec[a].push_back(b);
vec[b].push_back(a);
}
cout<<dfs(1,0)<<endl;
return 0;
}