codeforces580C
Kefa and Park
一棵以1为根的树,树上有些点是红的。一个叶子是合法的当且仅当从根到它的路径上出现的连续红点个数不超过m。求有多少个叶子是合法的。Input
第一行两个整数n和m(2≤n ≤105,1≤m≤n)
第二行n个整数0或1,如果是1,表示第i个点是红点。
接下来n-1行,每行两个整数x和y,表示树上的一条边。Output输出满足条件的叶子节点数Examples
Input
4 1
1 1 0 0
1 2
1 3
1 4
Output
2
Input
7 1
1 0 1 1 0 0 0
1 2
1 3
2 4
2 5
3 6
3 7
Output
2
Note
第一个样例 红点已经被标记出来了。叶子节点是2,3,4. 编号为2的叶子节点不合法
第二个样例: 叶子节点是4, 5, 6, 7.其中 6,7不合法.
sol:暴力dfs是O(n)的,dfs时多记一个变量表示当前连续几个红点了,当然答案也可以从父亲那里转移
判断是否是叶子就要多记两个变量入度和出度,因为是双向边,所以in和out都为1的就是叶子
#include <bits/stdc++.h> using namespace std; typedef int ll; inline ll read() { ll s=0; bool f=0; char ch=' '; while(!isdigit(ch)) { f|=(ch=='-'); ch=getchar(); } while(isdigit(ch)) { s=(s<<3)+(s<<1)+(ch^48); ch=getchar(); } return (f)?(-s):(s); } #define R(x) x=read() inline void write(ll x) { if(x<0) { putchar('-'); x=-x; } if(x<10) { putchar(x+'0'); return; } write(x/10); putchar((x%10)+'0'); return; } #define W(x) write(x),putchar(' ') #define Wl(x) write(x),putchar('\n') const int N=100005,M=200005; int n,m,Cor[N]; namespace Tree { int tot=0,Next[M],to[M],head[M]; int Num[N],Indeg[N],Outdeg[N]; inline void add(int x,int y) { Indeg[y]++; Outdeg[x]++; Next[++tot]=head[x]; to[tot]=y; head[x]=tot; return; } inline void dfs(int x,int fa,int cnt) { int i; Num[x]=max(Num[x],cnt); for(i=head[x];i;i=Next[i]) if(to[i]!=fa) { Num[to[i]]=max(Num[to[i]],Num[x]); if(Cor[to[i]]) { dfs(to[i],x,cnt+1); } else { dfs(to[i],x,0); } } return; } inline int Solve() { int i,ans=0; Num[1]=Cor[1]; dfs(1,0,Num[1]); for(i=2;i<=n;i++) if(Indeg[i]==1&&Outdeg[i]==1) { if(Num[i]<=m) ans++; } return ans; } } int main() { int i; R(n); R(m); for(i=1;i<=n;i++) R(Cor[i]); for(i=1;i<n;i++) { int x=read(),y=read(); Tree::add(x,y); Tree::add(y,x); } Wl(Tree::Solve()); return 0; }
河田は河田、赤木は赤木……。
私は誰ですか。教えてください、私は誰ですか。
そうだ、俺はあきらめない男、三井寿だ!