zoukankan      html  css  js  c++  java
  • 【BZOJ1468】Tree

    Description

    给你一棵TREE,以及这棵树上边的距离.问有多少对点它们两者间的距离小于等于K

    Input

    N(n<=40000) 接下来n-1行边描述管道,按照题目中写的输入 接下来是k

    Output

    一行,有多少对点之间的距离小于等于k

    Sample Input

    7
    1 6 13
    6 3 9
    3 5 7
    4 1 3
    2 4 20
    4 7 2
    10

    Sample Output

    5
     
    又是一道点分治的题,方法同聪聪可可。
     1 #include<cstdio>
     2 #include<algorithm>
     3 using namespace std;
     4 const int N=40010;
     5 int deep[N],head[N],son[N],f[N],d[N],root,ans,n,sum,cnt,k;
     6 bool vis[N];
     7 struct ee{int to,next,w;}e[N*2];
     8 void insert(int u,int v,int w){
     9     e[++cnt].to=v;e[cnt].next=head[u];e[cnt].w=w;head[u]=cnt;
    10 }
    11  
    12 void getroot(int x,int fa){
    13     son[x]=1;f[x]=0;
    14     for (int i=head[x];i;i=e[i].next){
    15         int v=e[i].to;
    16         if (vis[v]||v==fa) continue;
    17         getroot(v,x);
    18         son[x]+=son[v];
    19         f[x]=max(f[x],son[v]);
    20     }
    21     f[x]=max(f[x],sum-f[x]);
    22     if (f[x]<f[root]) root=x;
    23 }
    24  
    25 void getdeep(int x,int fa){
    26     deep[++deep[0]]=d[x];
    27     for (int i=head[x];i;i=e[i].next){
    28         int v=e[i].to;
    29         if (vis[v]||v==fa) continue;
    30         d[v]=d[x]+e[i].w;
    31         getdeep(v,x);
    32     }
    33 }
    34  
    35 int cal(int x,int now){
    36     int t=0;
    37     d[x]=now;deep[0]=0;
    38     getdeep(x,0);
    39     sort(deep+1,deep+deep[0]+1);
    40     int l=1,r=deep[0];
    41     for (;l<r;) if (deep[l]+deep[r]<=k){t+=r-l;l++;}
    42                 else r--;
    43     return t;
    44 }
    45  
    46 void work(int x){
    47     ans+=cal(x,0);
    48     vis[x]=1;
    49     for (int i=head[x];i;i=e[i].next){
    50         int v=e[i].to;
    51         if (!vis[v]) {
    52             ans-=cal(v,e[i].w);sum=son[v];root=0;
    53             getroot(v,0);
    54             work(root);
    55         }
    56     }
    57 }
    58  
    59 int main(){
    60     scanf("%d",&n);
    61     int u,v,w;
    62     for (int i=1;i<n;i++){
    63         scanf("%d%d%d",&u,&v,&w);
    64         insert(u,v,w);
    65         insert(v,u,w);
    66     }
    67     f[0]=sum=n;
    68     scanf("%d",&k);
    69     getroot(1,0);
    70     work(root);
    71     printf("%d",ans); 
    72 }
  • 相关阅读:
    猜数字游戏
    发红包程序
    实现微信摇一摇部分功能
    计算1+1/2+1/3+....+1/100的值
    约瑟夫问题
    简易计时器
    简易学生管理系统
    文件加密解密
    分鱼问题
    分橘子问题
  • 原文地址:https://www.cnblogs.com/wuminyan/p/5140596.html
Copyright © 2011-2022 走看看