树上倍增。
#include<iostream> #include<cstdio> #include<cstring> #define maxv 100500 #define maxe 200500 using namespace std; struct edge { int v,nxt; }e[maxe]; int n,s,w[maxv],dis[maxv],x,y,nume=0,g[maxv],root,anc[maxv][20],sum[maxv][20],ans=0; bool vis[maxv]; void addedge(int u,int v) { e[++nume].v=v; e[nume].nxt=g[u]; g[u]=nume; } void dfs(int now) { for (int i=g[now];i;i=e[i].nxt) { int v=e[i].v; dis[v]=dis[now]+1; anc[v][0]=now; sum[v][0]=w[now]; dfs(v); } } int find(int x) { int regis=w[x],now=x; for (int ee=19;ee>=0;ee--) { if (regis+sum[now][ee]<=s) { regis+=sum[now][ee]; now=anc[now][ee]; } } if (regis==s) return 1; return 0; } int main() { scanf("%d%d",&n,&s); for (int i=1;i<=n;i++) scanf("%d",&w[i]); for (int i=1;i<=n-1;i++) { scanf("%d%d",&x,&y); addedge(x,y); vis[y]=true; } for (int i=1;i<=n;i++) { if (vis[i]==false) root=i; } dfs(root); for (int ee=1;ee<=19;ee++) for (int i=1;i<=n;i++) { anc[i][ee]=anc[anc[i][ee-1]][ee-1]; sum[i][ee]=sum[anc[i][ee-1]][ee-1]+sum[i][ee-1]; } for (int i=1;i<=n;i++) ans+=find(i); printf("%d ",ans); return 0; }