复制代码

板子 点分治

 

模板

  #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 ;
    }
 }
View Code

 

点分治 首先找 找树的重心

通过深度 找到各个点的距离 d

然后搜索 题目结果

已经封装三个函数

 

posted @ 2018-05-09 20:47  pg633  阅读(162)  评论(0编辑  收藏  举报