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

    用途

    大规模地处理树上路径

    做法

    先考虑对x为根的子树做dfs来处理x子树到x的路径,然后统计答案,然后再递归地做x的儿子...

    然而当树退化成链时,最差复杂度是$O(n^2)$的

    类比一维中二分的做法,其实是使左右区间尽量平均,那我们也让我们要处理的点的子树大小尽量平均

    具体来说,我们每次想要做x这个子树的时候,会想先在这个子树中找到一个点root,使得它的每个子树大小的最大值最小,然后将root作为这棵子树的新根,再继续处理路径

    我们通过dfs来统计子树的大小以选定root,需要注意的是,由于某个点的父亲将来也有可能变成它的孩子(如果它被选为根的话),那就也需要算父亲作为它的孩子时的大小,其实就是S-size[x],其中S是这棵树的总大小

    这样复杂度就是$O(nlogn)$的了

    然而还有一个很重要的问题:我在以x为根去dfs找路径的时候,可能会找到两个端点在同一个子树的情况,这显然是不合法的。我们可以有两种方法来处理这种情况

    1.(适用于大多数情况)在处理x的子树y的时候,先钦定住要走x到y这条边,也同样计算一波路径,这样算出来的就一定是刚才的不合法情况,减掉就完事了

    2.(适用于可以单独地对于某条路径O(1)地统计答案)我不做x,而是对x的每个儿子y,先用子树y统计答案,再用子树y更新答案,为以后的统计铺路,这样做,我统计到的答案一定不在同一个子树里,也就不会出现上面的问题。(例:bzoj2599 Race

    例题:

    luogu4178 求距离不超过K的路径数

     1 #include<bits/stdc++.h>
     2 #define pa pair<int,int>
     3 #define ll long long
     4 using namespace std;
     5 const int maxn=40040;
     6 
     7 inline ll rd(){
     8     ll x=0;char c=getchar();int neg=1;
     9     while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();}
    10     while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
    11     return x*neg;
    12 }
    13 
    14 struct Edge{
    15     int a,b,l,ne;
    16 }eg[maxn*2];
    17 int egh[maxn],ect;
    18 int N,K;
    19 int mins,smsiz,pct;
    20 int siz[maxn],dis[maxn],ans,fa[maxn];
    21 bool flag[maxn];
    22 
    23 inline void adeg(int a,int b,int l){
    24     eg[++ect].a=a;eg[ect].b=b;eg[ect].l=l;
    25     eg[ect].ne=egh[a];egh[a]=ect;
    26 }
    27 
    28 void getroot(int &rt,int x){
    29     int mm=0;siz[x]=1;
    30     for(int i=egh[x];i!=-1;i=eg[i].ne){
    31         int b=eg[i].b;if(b==fa[x]||flag[b]) continue;
    32         fa[b]=x;getroot(rt,b);
    33         siz[x]+=siz[b];mm=max(siz[b],mm);
    34     }mm=max(smsiz-siz[x],mm);
    35     if(mm<mins) mins=mm,rt=x;
    36 }
    37 
    38 void getdis(int x,int f,int d){
    39     dis[++pct]=d;
    40     for(int i=egh[x];i!=-1;i=eg[i].ne){
    41         int b=eg[i].b;if(b==f||flag[b]) continue;
    42         getdis(b,x,eg[i].l+d);
    43     }
    44 }
    45 
    46 int calc(int x,int tt){
    47     pct=0;getdis(x,0,tt);int re=0;
    48     sort(dis+1,dis+pct+1);
    49     int l=1,r=pct;
    50     while(l<r){
    51         if(dis[l]+dis[r]<=K) re+=r-l,l++;
    52         else r--;
    53     }return re;
    54 }
    55 
    56 void solve(int x){
    57     flag[x]=1;
    58     ans+=calc(x,0);
    59     for(int i=egh[x];i!=-1&&i;i=eg[i].ne){
    60         int b=eg[i].b;if(flag[b]) continue;
    61         ans-=calc(b,eg[i].l);
    62         mins=0x3f3f3f3f,smsiz=siz[b];
    63         int root=0;getroot(root,b);
    64         siz[fa[root]]=smsiz-siz[root];
    65         solve(root);
    66     }
    67 }
    68 
    69 int main(){
    70     int i,j,k;
    71     //freopen("4178.in","r",stdin);
    72     N=rd();memset(egh,-1,sizeof(egh));
    73     for(i=1;i<N;i++){
    74         int a=rd(),b=rd(),c=rd();
    75         adeg(a,b,c);adeg(b,a,c);
    76     }K=rd();
    77     smsiz=N;mins=0x3f3f3f3f;
    78     int root=0;getroot(root,1);
    79     solve(root);
    80     printf("%d
    ",ans);
    81 
    82     return 0;
    83 }
    luogu4178

    bzoj2599/luogu4149 求距离为K的路径的最小边数

     1 #include<bits/stdc++.h>
     2 #define pa pair<int,int>
     3 #define ll long long
     4 using namespace std;
     5 const int maxn=200020,maxk=1000010;
     6 
     7 inline ll rd(){
     8     ll x=0;char c=getchar();int neg=1;
     9     while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();}
    10     while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
    11     return x*neg;
    12 }
    13 
    14 int N,K;
    15 struct Edge{
    16     int b,ne,l;
    17 }eg[maxn*2];
    18 int egh[maxn],ect;
    19 int siz[maxn],pct;
    20 bool flag[maxn];
    21 int root,ms,smsiz;
    22 int dis[maxk],ans=0x3f3f3f3f;
    23 queue<int> dq;
    24 
    25 
    26 inline void adeg(int a,int b,int l){
    27     eg[++ect].b=b;eg[ect].l=l;eg[ect].ne=egh[a];egh[a]=ect;
    28 }
    29 
    30 void getroot(int x,int f){
    31     siz[x]=1;int mm=0;
    32     for(int i=egh[x];i;i=eg[i].ne){
    33         int b=eg[i].b;if(flag[b]||b==f) continue;
    34         getroot(b,x);
    35         siz[x]+=siz[b];mm=max(siz[b],mm);
    36     }mm=max(smsiz-siz[x],mm);
    37     if(mm<ms) ms=mm,root=x;
    38 }
    39 
    40 void getdis(int x,int f,int d,int dep){
    41     if(d<=K){
    42         if(dis[d]>2e5) dq.push(d);
    43         dis[d]=min(dis[d],dep);
    44     }else return;
    45     for(int i=egh[x];i;i=eg[i].ne){
    46         int b=eg[i].b;if(flag[b]||b==f) continue;
    47         getdis(b,x,d+eg[i].l,dep+1);
    48     }
    49 }
    50 void calans(int x,int f,int d,int dep){
    51     if(d<=K){
    52         if(dis[K-d]<=2e5) ans=min(ans,dep+dis[K-d]);
    53     }else return;
    54     for(int i=egh[x];i;i=eg[i].ne){
    55         int b=eg[i].b;if(flag[b]||b==f) continue;
    56         calans(b,x,d+eg[i].l,dep+1);
    57     }
    58 }
    59 
    60 inline void solve(int x){
    61     flag[x]=1;
    62     for(int i=egh[x];i;i=eg[i].ne){
    63         int b=eg[i].b;if(flag[b]) continue;
    64         calans(b,x,eg[i].l,1);
    65         getdis(b,x,eg[i].l,1);
    66     }while(!dq.empty()) dis[dq.front()]=0x3f3f3f3f,dq.pop();
    67     int ss=smsiz;
    68     for(int i=egh[x];i;i=eg[i].ne){
    69         int b=eg[i].b;if(flag[b]) continue;
    70         ms=0x3f3f3f3f;smsiz=siz[b]>siz[x]?ss-siz[x]:siz[b];
    71         getroot(b,x);solve(root);
    72     }
    73 }
    74 
    75 int main(){
    76     int i,j,k;
    77     N=rd(),K=rd(); 
    78     for(i=1;i<N;i++){
    79         int a=rd()+1,b=rd()+1,c=rd();
    80         adeg(a,b,c);adeg(b,a,c);
    81     }memset(dis,127,sizeof(dis));dis[0]=0;
    82     smsiz=N;ms=0x3f3f3f3f;getroot(1,0);
    83     solve(root);
    84     if(ans<=2e5) printf("%d
    ",ans);
    85     else printf("-1
    ");
    86     return 0;
    87 }
    bzoj2599
  • 相关阅读:
    OpenCascade Ray Tracing Rendering
    Create New Commands in Tcl
    OpenCascade Modeling Algorithms Fillets and Chamfers
    OpenCascade Modeling Algorithms Boolean Operations
    Construction of Primitives in Open Cascade
    Open Cascade Data Exchange STL
    Tcl Tk Introduction
    Open Cascade DataExchange IGES
    Netgen mesh library : nglib
    Hello Netgen
  • 原文地址:https://www.cnblogs.com/Ressed/p/9649159.html
Copyright © 2011-2022 走看看