題意:
一棵以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;
}