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

Solution

点分治模板

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;
12 int head[N],num_edge;
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;
19     edge[num_edge].next=head[u];
20     head[u]=num_edge;
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);
85         add(u,v,l); add(v,u,l);
86     }
87     scanf("%d",&k);
88     Get_root(1,0);
89     Solve(root);
90     printf("%d",ans);
91 }
posted @ 2018-04-01 10:38  Refun  阅读(130)  评论(0编辑  收藏  举报