• poj1741 Tree


    题目描述:

    给出一棵树,求距离不超过k的点对对数。

    题解:

    点分治板子题。

    对于一棵树,我们可以$O(n)$时间求出其重心。(重心:切开这个点得到一堆树,所有树的最大大小最小)

    如果我们将一棵树不断找重心->分开->找重心……,我们可以将这棵树分成若干部分。

    这个东西叫点分治。

    因此将一棵树不断分开后,每个点都会作一次中心。

    如果我们将第一层找到的重心称为一级重心,第二层找到的重心称为二级重心……的话,

    对于任意一条树链,经过的最高级重心只能有一个,而且从这个重心搜索一定可以搜到这条树链。

    这就是点分治能处理树链问题的原因。

    对于本题,我们可以求出以x为重心的树内距离x为i的有多少个点。

    然后对于和$<=k$的更新答案。

    但是还有一种情况,就是路径a为x->y->……,路径b为x->y->……,而a+b可以更新答案。

    这样我们的答案其实是偏大的。

    因此我们可以搞一下容斥,将y相同的直接搞掉,这样的话得出的就是答案了。

    代码:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define N 10050
    inline int rd()
    {
        int f=1,c=0;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){c=10*c+ch-'0';ch=getchar();}
        return f*c;
    }
    int n,k,hed[N],cnt;
    struct EG
    {
        int to,nxt,v;
    }e[2*N];
    void ae(int f,int t,int v)
    {
        e[++cnt].to = t;
        e[cnt].nxt = hed[f];
        e[cnt].v = v;
        hed[f] = cnt;
    }
    int rt,sum,mx[N],mrk[N],siz[N],ans;
    void get_rt(int u,int fa)
    {
        mx[u] = 0;siz[u] = 1;
        for(int j=hed[u];j;j=e[j].nxt)
        {
            int to = e[j].to;
            if(to==fa||mrk[to])continue;
            get_rt(to,u);
            siz[u]+=siz[to];
            if(siz[to]>mx[u])mx[u]=siz[to];
        }
        mx[u]=max(mx[u],sum-siz[u]);
        if(mx[u]<mx[rt])rt=u;
    }
    int st[N],tl;
    void dfs(int u,int fa,int dep)
    {
        st[++tl] = dep;
        for(int j=hed[u];j;j=e[j].nxt)
        {
            int to = e[j].to;
            if(to==fa||mrk[to])continue;
            dfs(to,u,dep+e[j].v);
        }
    }
    int sol(int u,int fa,int dep)
    {
        tl=0;
        dfs(u,fa,dep);
        sort(st+1,st+1+tl);
        int l = 1,r = tl,ret = 0;
        while(l<r)
        {
            if(st[l]+st[r]<=k)
            {
                ret+=r-l;
                l++;
            }else r--;
        }
        return ret;
    }
    void work()
    {
        ans+=sol(rt,0,0);
        mrk[rt]=1;
        for(int j=hed[rt];j;j=e[j].nxt)
        {
            int to = e[j].to;
            if(mrk[to])continue;
            ans-=sol(to,rt,e[j].v);
        }
        for(int j=hed[rt];j;j=e[j].nxt)
        {
            int to = e[j].to;
            if(mrk[to])continue;
            rt=0,sum=siz[to];
            get_rt(to,0);
            work();
        }
    }
    void init()
    {
        rt=sum=ans=cnt=0;
        memset(mrk,0,sizeof(mrk));
        memset(hed,0,sizeof(hed));
    }
    int main()
    {
        mx[0] = 0x7fffffff;
        while(1)
        {
            n=rd(),k=rd();
            init();
            if(!n&&!k)break;
            for(int f,t,v,i=1;i<n;i++)
            {
                f = rd(),t = rd(),v = rd();
                ae(f,t,v),ae(t,f,v);
            }
            rt=0;sum=n;
            get_rt(1,0);
            work();
            printf("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    Web安全学习笔记之更新kali国内源
    K8S学习笔记之二进制的方式创建一个Kubernetes集群
    K8S学习笔记之Kubernetes核心概念
    K8S学习笔记之修改K8S的api-server证书
    Docker学习笔记之Copy on Write机制
    ELK学习笔记之简单适用的ES集群监控工具cerebro安装使用
    ELK学习笔记之F5利用EELK进行应用数据挖掘系列(2)-DNS
    ELK学习笔记之F5利用ELK进行应用数据挖掘系列(1)-HTTP
    ELK学习笔记之F5-HTTP-requesting-logging logstash filter
    Debian 无线网卡驱动问题
  • 原文地址:https://www.cnblogs.com/LiGuanlin1124/p/10189889.html
Copyright © 2020-2023  润新知