zoukankan      html  css  js  c++  java
  • 洛谷P3806 【模板】点分治1

    题目背景

    感谢hzwer的点分治互测。

    题目描述

    给定一棵有n个点的树

    询问树上距离为k的点对是否存在。

    输入输出格式

    输入格式:

    n,m 接下来n-1条边a,b,c描述a到b有一条长度为c的路径

    接下来m行每行询问一个K

    输出格式:

    对于每个K每行输出一个答案,存在输出“AYE”,否则输出”NAY”(不包含引号)

    输入输出样例

    输入样例#1: 复制
    2 1
    1 2 2
    2
    输出样例#1: 复制
    AYE

    说明

    对于30%的数据n<=100

    对于60%的数据n<=1000,m<=50

    对于100%的数据n<=10000,m<=100,c<=1000,K<=10000000

    自己YY出来的一种做法

    慢的跟暴力一样

    我们考虑点分治的过程,

    用点分治可以快速计算出一个点到其他点的距离

    在这些距离中,不同子树的可以相加,同一子树的不能相加,需要特判

    对于查询操作,直接用数组记录权值为$k$的点是否出现过

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    using namespace std;
    const int MAXN=1e6+10;
    const int INF=1e7+10;
    inline char nc()
    {
        static char buf[MAXN],*p1=buf,*p2=buf;
        return p1==p2&&(p2=(p1=buf)+fread(buf,1,MAXN,stdin),p1==p2)?EOF:*p1++;
    }
    inline int read()
    {
        char c=nc();int x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=nc();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=nc();}
        return x*f;
    }
    struct node
    {
        int u,v,w,nxt;
    }edge[MAXN];
    int head[MAXN];
    int num=1;
    inline void AddEdge(int x,int y,int z)
    {
        edge[num].u=x;
        edge[num].v=y;
        edge[num].w=z;
        edge[num].nxt=head[x];
        head[x]=num++;
    }
    int F[MAXN],sum,siz[MAXN],vis[MAXN],root=0,cnt=0,deep[MAXN],can[MAXN];
    struct Ans
    {
        int v,id;
    }tot[MAXN];
    void GetRoot(int now,int fa)
    {
        siz[now]=1;
        for(int i=head[now];i!=-1;i=edge[i].nxt)
        {
            if(vis[edge[i].v]||edge[i].v==fa) continue;
            GetRoot(edge[i].v,now);
            siz[now]+=siz[edge[i].v];
            F[now]=max(F[now],siz[edge[i].v]);
        }
        F[now]=max(F[now],sum-F[now]);
        if(F[now]<F[root]) root=now;
    }
    void GetDeep(int now,int fa,int NowDeep,int num)
    {
        int cur=0;
        tot[++cnt].v=deep[now];
        tot[cnt].id=num;
        for(int i=head[now];i!=-1;i=edge[i].nxt)
        {
            if(vis[edge[i].v]||edge[i].v==fa) continue;
            deep[edge[i].v]=deep[now]+edge[i].w;
            if(NowDeep!=1) GetDeep(edge[i].v,now,NowDeep+1,num);
            else GetDeep(edge[i].v,now,NowDeep+1,cur++);
        }
    }
    void Work(int now)
    {
        cnt=0;deep[now]=0;
        GetDeep(now,0,1,1);
        for(int i=1;i<=cnt;i++)
            for(int j=i+1;j<=cnt;j++)
                if(tot[i].id!=tot[j].id) 
                     can[tot[i].v+tot[j].v]=1;
                else can[tot[i].v]=1,can[tot[j].v]=1;
    }
    void Solve(int now)
    {
        Work(now);
        vis[now]=1;
        for(int i=head[now];i!=-1;i=edge[i].nxt)
        {
            if(vis[edge[i].v]) continue;
            root=0;
            sum=siz[edge[i].v];
            GetRoot(edge[i].v,0);
            Solve(edge[i].v);
        }
    }
    int main()
    {
        #ifdef WIN32
        freopen("a.in","r",stdin);
        #else
        #endif 
        memset(head,-1,sizeof(head));
        int N=read(),M=read();
        for(int i=1;i<=N-1;i++)
        {
            int x=read(),y=read(),z=read();
            AddEdge(x,y,z);
            AddEdge(y,x,z);
        }
        root=0;
        F[0]=INF;
        sum=N;
        GetRoot(1,0);
        Solve(root);
        for(int i=1;i<=M;i++)
        {
            int p=read();
            if(can[p]) printf("AYE
    ");
            else        printf("NAY
    ");
        }
        return 0;
    }
  • 相关阅读:
    delphi 文件的读取(二进制文件和文本文件)
    delphi中用代码实现注册Ocx和Dll(有点怪异,使用CallWindowProc来调用指定函数DllRegisterServer)
    delphi 控件大全(确实很全)
    C#编写Windows 服务
    SSD Buffer Pool Extension
    .NET Web开发技术简单整理
    Python数据库访问之SQLite3、Mysql
    infiniband学习总结
    模板引擎开发3自定义标签的处理
    CSS选择器、优先级与匹配原理
  • 原文地址:https://www.cnblogs.com/zwfymqz/p/8148682.html
Copyright © 2011-2022 走看看