zoukankan      html  css  js  c++  java
  • BZOJ 1468 树分治

    求出子树的重心后求出它每个子节点的距离,排序后就可以统计距离小于等于K的点对的个数了,但是会在同一子树内重复,然后在每个子树里面减去小于等于K的点对个数就可以了。

     1 #include <iostream>
     2 #include <cstring>
     3 #include <cstdio>
     4 #include <algorithm>
     5 using namespace std;
     6 const int Maxn=10010;
     7 const int Inf=0x3f3f3f3f;
     8 int n,k,Root,u,v,w,Sum,Size[Maxn],Q[Maxn],F[Maxn],d[Maxn],cnt,head[Maxn],vis[Maxn],Top,Ans;
     9 struct EDGE{int to,next,w;}edge[Maxn<<2];
    10 inline int Max(int x,int y) {return x>y?x:y;}
    11 inline void Add(int u,int v,int w) {edge[cnt].to=v;edge[cnt].next=head[u];edge[cnt].w=w;head[u]=cnt++;}
    12 void Get_Root(int u,int fa)
    13 {
    14     Size[u]=1; F[u]=0;
    15     for (int i=head[u];i!=-1;i=edge[i].next)
    16     {
    17         int v=edge[i].to;
    18         if (v==fa || vis[v]) continue;
    19         Get_Root(v,u);
    20         Size[u]+=Size[v];
    21         F[u]=Max(F[u],Size[v]);
    22     }
    23     F[u]=Max(F[u],Sum-Size[u]);
    24     if (F[u]<F[Root]) Root=u;
    25 }
    26 void Get_Deep(int u,int fa)
    27 {
    28     Q[++Top]=d[u];
    29     for (int i=head[u];i!=-1;i=edge[i].next)
    30     {
    31         int v=edge[i].to;
    32         if (v==fa || vis[v]) continue;
    33         d[v]=d[u]+edge[i].w;
    34         Get_Deep(v,u);
    35     }
    36 }
    37 int Calc(int u,int value)
    38 {
    39     d[u]=value; Top=0; Get_Deep(u,0);
    40     sort(Q+1,Q+Top+1);
    41     int l=1,r=Top,Res=0;
    42     while (l<=r)
    43     {
    44         if (Q[l]+Q[r]<=k)
    45             Res+=r-l,l++; else r--;
    46     }
    47     return Res;
    48 }
    49 void Work(int u)
    50 {
    51     Ans+=Calc(u,0);  vis[u]=true;
    52     for (int i=head[u];i!=-1;i=edge[i].next)
    53     {
    54         int v=edge[i].to;
    55         if (vis[v]) continue;
    56         Ans-=Calc(v,edge[i].w);
    57         Sum=Size[v]; Root=0;
    58         Get_Root(v,u);
    59         Work(Root);
    60     }
    61 }
    62 int main()
    63 {
    64     while (scanf("%d%d",&n,&k)!=EOF)
    65     {
    66         if (n==0 && k==0) break;
    67         Ans=0; cnt=0; memset(head,-1,sizeof(head));
    68         for (int i=1;i<n;i++)
    69         {
    70             scanf("%d%d%d",&u,&v,&w);
    71             Add(u,v,w),Add(v,u,w);
    72         }
    73         memset(vis,false,sizeof(vis));
    74         Sum=n; F[0]=Inf;
    75         Get_Root(1,0);
    76         Work(Root);
    77         printf("%d
    ",Ans);
    78     }
    79     return 0;
    80 }
    C++
     
  • 相关阅读:
    .net程序运行
    vc mscom控件串口接收不到数据问题
    vc 显示非模态对话框
    vc 使用SetWindowPos改变窗体的大小,实现折叠,展开
    c# 串口问题
    vc 电脑发声程序
    Java问题定位技术
    Java性能调优笔记
    shell解析xml文档
    Unix/Linux 的 Load 初级解释
  • 原文地址:https://www.cnblogs.com/yyjxx2010xyu/p/5994522.html
Copyright © 2011-2022 走看看