按理来说是一个非常简单的树分治,我只是为了将专题的时候作为一道引入题目的,不过,我擦set和map的常数差别有那么大吗,map居然比set慢了10倍,然后就一直T啊一直T最后看他们都用的set改过来就A了,我也是郁闷。
方法很简单,用set记录一个长度有没有出现过,然后每次树分治统计
#include<cstdio>
#include<cstring>
#include<iostream>
#include<set>
#include<cstdlib>
#define maxn 30010
#define maxm 1000020
using namespace std;
int head[maxn],tot,dis[maxn],n,m,q[maxn],f[maxn],s[maxn],size,rt,vis[maxn],ans[maxn];
struct edge{int v,next,w;}e[maxn*2];
void adde(int a,int b,int c){e[tot].v=b,e[tot].w=c,e[tot].next=head[a];head[a]=tot++;}
set<int>Map;
void getrt(int u,int fa){
f[u]=0,s[u]=1;
for(int v,i=head[u];i!=-1;i=e[i].next){
if(vis[v=e[i].v]||v==fa)continue;
getrt(v,u);
s[u]+=s[v];
f[u]=max(f[u],s[v]);
}
f[u]=max(f[u],size-f[u]);
if(f[u]<f[rt])rt=u;
}
int cur[maxn*2],p;
void dfs(int u,int fa){
cur[++p]=dis[u];
for(int v,i=head[u];i!=-1;i=e[i].next){
if(vis[v=e[i].v]||v==fa)continue;
dis[v]=dis[u]+e[i].w;
dfs(v,u);
}
}
void calc(int u){
Map.clear();Map.insert(0);
for(int v,i=head[u];i!=-1;i=e[i].next){
if(vis[v=e[i].v])continue;
dis[v]=e[i].w,p=0;
dfs(v,u);
for(int j=1;j<=p;j++){
for(int k=1;k<=m;k++){
if(Map.find(q[k]-cur[j])!=Map.end())ans[k]++;
}
}
for(int j=1;j<=p;j++)Map.insert(cur[j]);
}
}
void solve(int u){
vis[u]=1;
calc(u);
for(int i=head[u],v;i!=-1;i=e[i].next){
if(vis[v=e[i].v])continue;
f[rt=0]=size=s[v];
getrt(v,u);
solve(rt);
}
}
int main(){
memset(head,-1,sizeof(head));
scanf("%d%d",&n,&m);
for(int a,b,c,i=1;i<n;i++){
scanf("%d%d%d",&a,&b,&c);
adde(a,b,c),adde(b,a,c);
}
for(int i=1;i<=m;i++)scanf("%d",q+i);
f[rt=0]=size=n;
getrt(1,1);
solve(rt);
for(int i=1;i<=m;i++)if(ans[i]>0||q[i]==0)
puts("Yes");else puts("No");
return 0;
}