[学习笔记]点分治
壹、模板测试连接
贰、具体分析
留坑,待补。
叁、代码
using namespace Elaina;
const int inf=0x3f3f3f3f;
const int maxn=1e4;
const int maxm=100;
const int maxk=1e7;
struct edge{int to,nxt,w;;
edge(){}
edge(const int T,const int N,const int W):to(T),nxt(N),w(W){}
}e[maxn*2+5];
int tail[maxn+5],ecnt;
inline void add_edge(const int u,const int v,const int w){
e[ecnt]=edge(v,tail[u],w);tail[u]=ecnt++;
e[ecnt]=edge(u,tail[v],w);tail[v]=ecnt++;
}
int n,m;
int q[maxm+5],ans[maxm+5];
inline void input(){
n=readin(1),m=readin(1);
memset(tail+1,-1,sizeof(tail[0])*n);
int u,v,w;
rep(i,1,n-1){
u=readin(1),v=readin(1),w=readin(1);
add_edge(u,v,w);
}
rep(i,1,m)q[i]=readin(1);
}
/* record the maximum size of it's sons */ ;
int f[maxn+5];
/* use to calculate f[] */ ;
int siz[maxn+5];
/* whether this node has been a gravity center*/ ;
int use[maxn+5];
void findrt(const int u,const int par,const int n,int& root){
siz[u]=1,f[u]=0;
for(int i=tail[u],v;~i;i=e[i].nxt)if((v=e[i].to)!=par && !use[v]){
findrt(v,u,n,root);
siz[u]+=siz[v],f[u]=Max(f[u],siz[v]);
}
f[u]=Max(f[u],n-siz[u]);
if(f[u]<f[root])root=u;
}
int cur[maxn+5],dis[maxn+5],ed;
/**
* @brief while get the dis from other point to the current root, recalculate the size
*/
void getdis(const int u,const int par){
siz[u]=1;
cur[++ed]=dis[u];
for(int i=tail[u],v;~i;i=e[i].nxt)if(!use[v=e[i].to] && v!=par){
dis[v]=dis[u]+e[i].w;
getdis(v,u);
siz[u]+=siz[v];
}
}
int exist[maxk+5],cls[maxn+5];
void solve(const int u){
int clscnt=1; // exist[0] should also be cleared
exist[0]=1;
for(int i=tail[u],v;~i;i=e[i].nxt)if(!use[v=e[i].to]){
ed=0,dis[v]=e[i].w; getdis(v,u);
for(int j=1;j<=ed;++j)for(int k=1;k<=m;++k)
if(q[k]>=cur[j])ans[k]|=exist[q[k]-cur[j]];
for(int j=1;j<=ed;++j)if(cur[j]<=maxk){
cls[++clscnt]=cur[j];
exist[cur[j]]=1;
}
}
for(int i=1;i<=clscnt;++i)exist[cls[i]]=0;
}
void launch(const int u,const int v);
void divide(const int u){
use[u]=1,solve(u);
for(int i=tail[u],v;~i;i=e[i].nxt)if(!use[v=e[i].to]){
// the reason we can use siz is we've recalculate siz[] while invoking solve(u)
launch(v,siz[v]);
}
}
/**
* @brief solve the subtre (represented by node @p u )
* @param u the current node, represent it's subtre
* @param n the number of the nodes of the subtre
*/
void launch(const int u,const int n){
int root=0;f[0]=inf;
findrt(u,0,n,root);
divide(root);
}
signed main(){
input();
launch(1,n);
rep(i,1,m)if(ans[i])printf("AYE\n");
else printf("NAY\n");
return 0;
}