• 解题:洛谷4178 Tree


    题面

    重(新)学点分治中......

    普通的点分治一般这几步:

    1.找重心

    2.从重心开始DFS,得到信息

    3.统计经过重心的路径

    4.分别分治几棵子树,继续这个过程

    然后是常见的(制杖的我的)一些疑问

    1.这么统计不会漏吗

    不会,你递归进子树的时候经过当前重心的已经统计完了,分别统计子树就行

    2.这么统计不会重吗

    不会,因为你进子树不会往回走(这俩都是啥问题啊。。。)

    3.复杂度?

    $O(nlog n)$,根据重心的性质可得

    这个题把所有路径排个序然后双指针扫即可,复杂度$O(nlog n)$

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 const int N=40005,inf=1e9;
     6 int siz[N],vis[N],dis[N],mem[N];
     7 int p[N],noww[2*N],goal[2*N],val[2*N];
     8 int n,k,c,t1,t2,t3,cnt,lp,rp,nsiz,maxx;
     9 long long ans;
    10 void Link(int f,int t,int v)
    11 {
    12     noww[++cnt]=p[f],p[f]=cnt;
    13     goal[cnt]=t,val[cnt]=v;
    14 }
    15 void Mark(int nde,int fth)
    16 {
    17     siz[nde]=1; int tmp=0;
    18     for(int i=p[nde];i;i=noww[i])
    19         if(goal[i]!=fth&&!vis[goal[i]]) 
    20         {
    21             Mark(goal[i],nde);
    22             siz[nde]+=siz[goal[i]];
    23             tmp=max(tmp,siz[goal[i]]);
    24         }
    25     tmp=max(tmp,nsiz-siz[nde]);
    26     if(tmp<maxx) maxx=tmp,c=nde;
    27 }
    28 void DFS(int nde,int fth)
    29 {
    30     mem[++rp]=dis[nde];
    31     for(int i=p[nde];i;i=noww[i])
    32         if(goal[i]!=fth&&!vis[goal[i]])
    33         {
    34             dis[goal[i]]=dis[nde]+val[i];
    35             DFS(goal[i],nde);
    36         }
    37 }
    38 int Getans(int nde,int fir)
    39 {
    40     lp=1,rp=0,dis[nde]=fir,DFS(nde,0);
    41     long long ret=0;
    42     sort(mem+1,mem+1+rp);
    43     while(lp<rp)
    44         (mem[lp]+mem[rp]<=k)?ret+=rp-lp,lp++:rp--;
    45     return ret;
    46 }
    47 void PDC(int nde)
    48 {
    49     ans+=Getans(nde,0),vis[nde]=true;
    50     for(int i=p[nde];i;i=noww[i])
    51         if(!vis[goal[i]])
    52         {
    53             ans-=Getans(goal[i],val[i]);
    54             nsiz=siz[goal[i]],maxx=inf;
    55             Mark(goal[i],0),PDC(c);
    56         }
    57 }
    58 int main()
    59 {
    60     scanf("%d",&n);
    61     for(int i=1;i<n;i++)
    62     {
    63         scanf("%d%d%d",&t1,&t2,&t3);
    64         Link(t1,t2,t3),Link(t2,t1,t3);
    65     }
    66     scanf("%d",&k),nsiz=n,maxx=inf;
    67     Mark(1,0),PDC(c),printf("%lld",ans);
    68     return 0;
    69 }
    View Code
  • 相关阅读:
    day9习题
    生产者消费者模型(吃包子例子)
    map 函数----filter函数
    #返回值包含函数
    #把函数当作参数传给另一个函数
    异常和错误!
    递归调用
    局部和全局案例!!
    全局变量与局部变量2
    全局变量与局部变量
  • 原文地址:https://www.cnblogs.com/ydnhaha/p/10162456.html
Copyright © 2020-2023  润新知