将块想象为树枝,由高级点向低级点分子树,最后分成n个点,暴力求解
- Get_rt
找到当前分治树的重心
use[v]=>防止从更优级分治的点(祖先)的越界
inline void Get_rt(int x,int fa)
{
f[x]=0;size[x]=1;
for(int i=hd[x];i;i=e[i].nt)
{
int v=e[i].to;
if(use[v]||v==fa)continue;
Get_rt(v,x);
size[x]+=size[v];
f[x]=max(f[x],size[v]);
}
f[x]=max(f[x],SIZE-size[x]);
if(f[x]<f[rt])rt=x;
}
- Dfs:分治
pc[0]=1;可能有边权为0的点
cala:计算当前分治结果
inline void dfs(int x)
{
use[x]=1;pc[0]=1;
cala(x);
for(int i=hd[x];i;i=e[i].nt)
{
int v=e[i].to;
if(use[v])continue;
f[rt=0]=n;SIZE=size[v];
Get_rt(v,x);
dfs(rt);
}
}
- Cala
inline void cala(int x)
{
int p=0;
int c[maxn];//记录当前分治下存在路径情况
for(int i=hd[x];i;i=e[i].nt)
{
int v=e[i].to;
if(use[v])continue;
cnt[0]=0;//统计路个数
//cnt:统计路径长度
dis[v]=e[i].val;
//分治初始路径长度
Get_dis(v,x);
//得到路径长度
for(int j=1;j<=cnt[0];++j)
for(int k=1;k<=m;++k)
if(q[k]>=cnt[j])ans[k]|=pc[q[k]-cnt[j]];
//与答案匹配
for(int j=1;j<=cnt[0];++j)
c[++p]=cnt[j],pc[cnt[j]]=1;
//分治点内打标记
}
inc(i,1,p)pc[c[i]]=0;
//还原,为了下次使用
}
- Get_dis
累加求长度
inline void Get_dis(int x,int fa)
{
cnt[++cnt[0]]=dis[x];
for(int i=hd[x];i;i=e[i].nt)
{
int v=e[i].to;
if(use[v]||v==fa)continue;
dis[v]=dis[x]+e[i].val;
Get_dis(v,x);
}
}
完整代码
#include<bits/stdc++.h>
#define re return
#define inc(i,l,r) for(int i=l;i<=r;++i)
const int maxn=1e5+5,maxm=305;
using namespace std;
template<typename T>inline void rd(T&x)
{
char c;bool f=0;
while((c=getchar())<'0'||c>'9')if(c=='-')f=1;
x=c^48;
while((c=getchar())>='0'&&c<='9')x=x*10+(c^48);
if(f)x=-x;
}
int size[maxn],n,m,dis[maxn],rt,SIZE,hd[maxn],f[maxn],pc[maxn];
int k,cnt[maxn],q[maxn],use[maxn],ans[maxn];
struct node{
int to,nt,val;
}e[maxn<<1];
inline void add(int x,int y,int z)
{
e[++k].to=y;e[k].nt=hd[x];hd[x]=k;e[k].val=z;
e[++k].to=x;e[k].nt=hd[y];hd[y]=k;e[k].val=z;
}
inline void Get_rt(int x,int fa)
{
f[x]=0;size[x]=1;
for(int i=hd[x];i;i=e[i].nt)
{
int v=e[i].to;
if(use[v]||v==fa)continue;
Get_rt(v,x);
size[x]+=size[v];
f[x]=max(f[x],size[v]);
}
f[x]=max(f[x],SIZE-size[x]);
if(f[x]<f[rt])rt=x;
}
inline void Get_dis(int x,int fa)
{
cnt[++cnt[0]]=dis[x];
for(int i=hd[x];i;i=e[i].nt)
{
int v=e[i].to;
if(use[v]||v==fa)continue;
dis[v]=dis[x]+e[i].val;
Get_dis(v,x);
}
}
inline void cala(int x)
{
int p=0;
int c[maxn];
for(int i=hd[x];i;i=e[i].nt)
{
int v=e[i].to;
if(use[v])continue;
cnt[0]=0;dis[v]=e[i].val;
Get_dis(v,x);
for(int j=1;j<=cnt[0];++j)
for(int k=1;k<=m;++k)
if(q[k]>=cnt[j])ans[k]|=pc[q[k]-cnt[j]];
for(int j=1;j<=cnt[0];++j)
c[++p]=cnt[j],pc[cnt[j]]=1;
}
inc(i,1,p)pc[c[i]]=0;
}
inline void dfs(int x)
{
use[x]=1;pc[0]=1;
cala(x);
for(int i=hd[x];i;i=e[i].nt)
{
int v=e[i].to;
if(use[v])continue;
f[rt=0]=n;SIZE=size[v];
Get_rt(v,x);
dfs(rt);
}
}
int main()
{
freopen("in.txt","r",stdin);
int x,y,z;
rd(n),rd(m);
inc(i,2,n)
{
rd(x),rd(y),rd(z);
add(x,y,z);
}
inc(i,1,m)rd(q[i]);
f[rt]=SIZE=n;
Get_rt(1,0);
dfs(rt);
inc(i,1,m)
if(ans[i])
printf("AYE
");
else printf("NAY
");
re 0;
}