# BZOJ1468:Tree(点分治)

## Input

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

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

5

## Code

 1 #include<iostream>
2 #include<cstring>
3 #include<cstdio>
4 #include<algorithm>
5 #define N (40000+10)
6 using namespace std;
7 struct node
8 {
9     int to,next,len;
10 }edge[N*2];
11 int n,k,sum,root,ans;
13 int depth[N],d[N],size[N],maxn[N];
14 bool vis[N];
15 void add(int u,int v,int l)
16 {
17     edge[++num_edge].to=v;
18     edge[num_edge].len=l;
21 }
22
23 void Get_root(int x,int fa)
24 {
25     size[x]=1; maxn[x]=0;
26     for (int i=head[x];i!=0;i=edge[i].next)
27         if (edge[i].to!=fa && !vis[edge[i].to])
28         {
29             Get_root(edge[i].to,x);
30             size[x]+=size[edge[i].to];
31             maxn[x]=max(maxn[x],size[edge[i].to]);
32         }
33     maxn[x]=max(maxn[x],sum-size[x]);
34     if (maxn[x]<maxn[root]) root=x;
35 }
36
37 void Get_depth(int x,int fa)
38 {
39     depth[++depth[0]]=d[x];
40     for (int i=head[x];i!=0;i=edge[i].next)
41         if (edge[i].to!=fa && !vis[edge[i].to])
42         {
43             d[edge[i].to]=d[x]+edge[i].len;
44             Get_depth(edge[i].to,x);
45         }
46 }
47
48 int Calc(int x,int cost)
49 {
50     d[x]=cost; depth[0]=0;
51     Get_depth(x,0);
52     sort(depth+1,depth+depth[0]+1);
53     int l=1,r=depth[0],cnt=0;
54     while (l<r)
55         if (depth[l]+depth[r]<=k)
56             cnt+=r-l,l++;
57         else
58             r--;
59     return cnt;
60 }
61
62 void Solve(int x)
63 {
64     ans+=Calc(x,0);
65     vis[x]=true;
66     for (int i=head[x];i!=0;i=edge[i].next)
67         if (!vis[edge[i].to])
68         {
69             ans-=Calc(edge[i].to,edge[i].len);
70             sum=size[edge[i].to];
71             root=0;
72             Get_root(edge[i].to,0);
73             Solve(root);
74         }
75 }
76
77 int main()
78 {
79     int u,v,l;
80     scanf("%d",&n);
81     sum=maxn[0]=n;
82     for (int i=1;i<=n-1;++i)
83     {
84         scanf("%d%d%d",&u,&v,&l);
91 }