zoukankan      html  css  js  c++  java
  • [模板] 点分治

    之前搞了一个树的中心,结果当时把点分治给扔下了,现在搞一搞。其实点分治的分治思想很明显,就是把树切成一个个小树,然后在重心的位置再分治就行了。

    代码实现有一定困难,但就我觉得前一个函数和树刨的dfs1很像吗,详情见代码。

    题干:

    题目背景
    
    感谢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

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<ctime>
    #include<queue>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    #define duke(i,a,n) for(int i = a;i <= n;i++)
    #define lv(i,a,n) for(int i = a;i >= n;i--)
    #define clean(a) memset(a,0,sizeof(a))
    const int INF = 1 << 30;
    typedef long long ll;
    typedef double db;
    template <class T>
    void read(T &x)
    {
        char c;
        bool op = 0;
        while(c = getchar(), c < '0' || c > '9')
            if(c == '-') op = 1;
        x = c - '0';
        while(c = getchar(), c >= '0' && c <= '9')
            x = x * 10 + c - '0';
        if(op) x = -x;
    }
    template <class T>
    void write(T x)
    {
        if(x < 0) putchar('-'), x = -x;
        if(x >= 10) write(x / 10);
        putchar('0' + x % 10);
    }
    struct node
    {
        int l,r,nxt,w;
    } a[40005];
    int lst[40005],len = 0,n,m;
    void add(int x,int y,int w)
    {
        a[++len].l = x;
        a[len].r = y;
        a[len].w = w;
        a[len].nxt = lst[x];
        lst[x] = len;
    }
    int qu[405],maxp[40005],sum,rt = 0,siz[40005];
    int vis[40005],judge[10000000],test[10000000];
    int q[40005],dis[40005],rem[40005];
    void getrt(int u,int pa)
    {
        siz[u] = 1;
        maxp[u] = 0;
        for(int k = lst[u]; k; k = a[k].nxt)
        {
            int y = a[k].r;
            if(y == pa || vis[y])
                continue;
            getrt(y,u);
            siz[u] += siz[y];
            maxp[u] = max(maxp[u],siz[y]);
        }
        maxp[u] = max(maxp[u],sum - siz[u]);
        if(maxp[u] < maxp[rt])
            rt = u;
    }
    void getdis(int u,int fa)
    {
        rem[++rem[0]] = dis[u];//主要是这一句,就是rem中存了所有可能的长度 
        for(int k = lst[u]; k; k = a[k].nxt)
        {
            int y = a[k].r;
            if(y == fa || vis[y] == 1)
                continue;
            dis[y] = dis[u] + a[k].w;//记录子树中的距离 
            getdis(y,u);
        }
    }
    void calc(int u)
    {
        int p = 0;
        for(int k = lst[u]; k; k = a[k].nxt)
        {
            int y = a[k].r;
            if(vis[y] == 1)
                continue;
            rem[0] = 0;
            dis[y] = a[k].w;
            getdis(y,u);
            lv(j,rem[0],1)
            {
                duke(i,1,m)
                {
                    if(qu[i] >= rem[j])
                        test[i] |= judge[qu[i] - rem[j]];//尝试匹配 
                }
            } 
            lv(j,rem[0],1)
            {
                q[++p] = rem[j];//就是一个过程量 
                judge[rem[j]] = 1;
            } 
        } 
        duke(i,1,p)
        judge[q[i]] = 0;//清空当前子树judge数组 
    }
    void solve(int u)
    {
        vis[u] = judge[0] = 1;
        calc(u);
        for(int k = lst[u]; k; k = a[k].nxt)
        {
            int y = a[k].r;
            if(vis[y])
                continue;
            sum = siz[y];
            maxp[rt = 0] = INF;
            getrt(y,0);
            solve(rt);
        }
    }
    int main()
    {
        read(n);
        read(m);
        duke(i,1,n - 1)
        {
            int x,y,w;
            read(x);
            read(y);
            read(w);
            add(x,y,w);
            add(y,x,w);
        }
        duke(i,1,m)
        read(qu[i]);
        maxp[rt] = sum = n;
        getrt(1,0);
    //    cout<<"QAQ"<<endl; 
        solve(rt);
        duke(i,1,m)
        {
            if(test[i])
                printf("AYE
    ");
            else
                printf("NAY
    ");
        }
        return 0;
    }
  • 相关阅读:
    PHP对象的遍历
    PHP对象的复制
    PHP面向对象之类的自动加载
    PHP面向对象之接口
    PHP面向对象之重载
    PHP面向对象之抽象类,抽象方法
    PHP面向对象之final关键字
    PHP面向对象之重写
    使用python操作word
    vc++使用cookie登录网站
  • 原文地址:https://www.cnblogs.com/DukeLv/p/9693656.html
Copyright © 2011-2022 走看看