zoukankan      html  css  js  c++  java
  • 点分治模板(洛谷P4178 Tree)(树分治,树的重心,容斥原理)

    推荐YCB的总结

    推荐你谷ysn等巨佬的详细题解

    大致流程——

    1. dfs求出当前树的重心

    2. 对当前树内经过重心的路径统计答案(一条路径由两条由重心到其它点的子路径合并而成)

    3. 容斥减去不合法情况(两条子路径在重心的子树内就已经相交)

    4. 删除重心(打上永久标记),对子树继续处理,转1

    求重心是板子,算答案的方法要依题而定,一般都要容斥。

    模板题洛谷传送门

    calc函数中,头尾两个指针扫的计数方法也是一种套路

    因为要sort,所以复杂度(O(nlog^2n)),不过蒟蒻实测你谷数据(k)不超过(40000),所以可以改用桶排序,复杂度降到(O(n(log n+log k)))

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define RG register
    #define I inline
    #define R RG int
    #define G c=getchar()
    using namespace std;
    const int N=4e5+9,M=8e5+9;
    int n,k,p,rt,ans,he[N],ne[M],to[M],l[M],mx[N],s[N],b[N];
    bool vis[N];
    I void max(R&x,R y){if(x<y)x=y;}
    I int in(){
        RG char G;
        while(c<'-')G;
        R x=c&15;G;
        while(c>'-')x*=10,x+=c&15,G;
        return x;
    }
    void getrt(R x){//求重心模板
        vis[x]=1;s[x]=1;mx[x]=0;
        for(R y,i=he[x];i;i=ne[i]){
            if(vis[y=to[i]])continue;
            getrt(y);
            s[x]+=s[y];max(mx[x],s[y]);
        }
        max(mx[x],n-s[x]);
        if(mx[rt]>mx[x])rt=x;
        vis[x]=0;
    }
    void getd(R x,R d){//统计长度不超过k的子路径
        if(d>k)return;
        vis[x]=1;b[++p]=d;
        for(R i=he[x];i;i=ne[i])
            if(!vis[to[i]])getd(to[i],d+l[i]);
        vis[x]=0;
    }
    I int calc(R x,R dis){//计算经过x的路径的答案
        p=0;getd(x,dis);
        sort(b+1,b+p+1);
        R ret=0,i=1,j=p;//双指针扫描计数
        while(i<=j)b[i]+b[j]>k?--j:ret+=j-i++;
        return ret;
    }
    void div(R x){//分治流程在此函数中得到体现
        getrt(x);
        ans+=calc(x=rt,0);
        vis[x]=1;rt=0;
        for(R t=n,y,i=he[x];i;i=ne[i]){
            if(vis[y=to[i]])continue;
            ans-=calc(y,l[i]);
            n=s[x]>s[y]?s[y]:t-s[x];
            div(y);
        }
    }
    int main(){
        mx[0]=1e9;
        n=in();
        for(R x,y,i=1;i<n;++i){
            x=in();y=in();
            ne[++p]=he[x];to[he[x]=p]=y;
            ne[++p]=he[y];to[he[y]=p]=x;
            l[p]=l[p-1]=in();
        }
        k=in();
        div(1);
        printf("%d
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    技术收集
    Entity Framework的扩展库
    暂时收集
    php 处理高并发的思路
    nginx缓存优先级(缓存问题者必看)
    mysql5.5主从配置
    php源码编译常见错误解决方案
    今天开始要改变模式了
    nrpe 在ubuntu上安装遇到的问题
    zendstudio 10下载汉化
  • 原文地址:https://www.cnblogs.com/flashhu/p/9351535.html
Copyright © 2011-2022 走看看