板子 点分治
模板
#include<bits/stdc++.h> using namespace std; #define LOACL freopen("in","r",stdin);\ freopen("out","w",stdout); #define REP(i,l,r) for(int i=l;i<=r;i++) #define Loop(i,u) for(int i=head[u];i;i=e[i].nxt) #define add(u,v,w) e[++tot]=(edge){head[u],v,w},head[u]=tot const int sz = (int)1e4+5; struct edge { int nxt,v,w; }e[sz<<1]; struct node { int dis,id; }rp[sz<<1]; int head[sz ],tot,tt,pp,n,m ,sum,root,f[sz],d[sz],son[sz]; bool vis[sz],ko[ sz<<10]; void dfs(int u,int fa) { son[u] = 1 ;f[u] = 0; Loop(i,u) { int v = e[i].v; if(vis[v]|| v==fa) continue; dfs(v,u); son[u] += son[v]; f[u]=max(f[u],son[v]); } f[u] =max(f[u],sum-son[u]); if(f[u]<f[root]) root =u; } void getdeep (int rearoot,int u,int fa,int ro) { Loop(i,u) { int v = e[i].v; if(vis[v]||v==fa) continue; d[v]=d[u]+e[i].w; if(u==rearoot) pp ++ ; if(u==rearoot)rp[++tt]=(node){d[v],pp}; else rp[++tt]=(node){d[v],ro}; ko[d[v]]=1; if(u==rearoot) getdeep(rearoot,v,u,pp); else getdeep(rearoot,v,u,ro); } } void getans (int u ) { d[u]=0;tt=0;pp=0; getdeep(u,u,0,0); vis[u]=1; REP(i,1,tt)REP(j,i+1,tt) if(rp[i].id!= rp[j].id) ko[rp[i].dis+rp[j].dis] =1; Loop(i,u) { int v=e[i].v; if(!vis[v]) { root=0; sum=son[v]; dfs(v,0); getans(root); } } } int main() { // LOACL cin>>n>>m; int u,v,w ; REP(i,1,n-1) { cin>>u>>v>>w; add(u,v,w); add(v,u,w); } sum=f[0]=n; root =0; dfs(1,0); getans(root); int kk; REP(i,1,m) { cin>>kk; if(ko[kk]==1) cout<<"AYE"<<endl; else cout<<"NAY"<<endl ; } }
点分治 首先找 找树的重心
通过深度 找到各个点的距离 d
然后搜索 题目结果
已经封装三个函数
不摸着石头过河,难道要在温柔乡睡到天昏地暗。