【bzoj 1648】Tree (点分治)

题目链接

bzoj & luogu

题目描述

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

解题思路

参考:(两篇都写的很好,我就是看这两篇学的)

https://blog.csdn.net/nixinyis/article/details/65445466

https://blog.csdn.net/qq_39553725/article/details/77542223

(期末在即)大坑待填。。。。

代码

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 const int maxn=90050;
 7 const int INF=99999999;
 8 int n,k,root,cnt=0,tot,num,ans=0;
 9 int head[maxn],ne[maxn],to[maxn],v[maxn],size[maxn],ma[maxn],dis[maxn];
10 bool vis[maxn];
11 inline void add(int f,int t,int w){
12     ne[++cnt]=head[f],head[f]=cnt,to[cnt]=t,v[cnt]=w;
13 }
14 inline void get_root(int now,int fa){
15     ma[now]=0,size[now]=1;
16     for(register int i=head[now];i;i=ne[i]){
17         if(to[i]==fa||vis[to[i]])continue;
18         get_root(to[i],now);
19         size[now]+=size[to[i]];
20         ma[now]=max(ma[now],size[to[i]]);
21     }
22     ma[now]=max(ma[now],tot-size[now]);
23     if(ma[now]<ma[root])root=now;
24 }
25 inline void get_dep(int now,int fa,int dist){
26     dis[++num]=dist;
27     for(register int i=head[now];i;i=ne[i]){
28         if(to[i]==fa||vis[to[i]])continue;
29         get_dep(to[i],now,dist+v[i]);
30     }
31 }
32 inline int calc(int now,int val){
33     num=0;
34     get_dep(now,0,val);
35     sort(dis+1,dis+num+1);
36     int l=1,r=num,tmp=0;
37     while(l<=r){
38         if(dis[l]+dis[r]<=k){
39             tmp+=r-l;
40             l++;
41         }
42         else r--;
43     }
44     return tmp;
45 }
46 inline void solve(int now){
47     ans+=calc(now,0),vis[now]=1;
48     for(register int i=head[now];i;i=ne[i]){
49         if(vis[to[i]])continue;
50         ans-=calc(to[i],v[i]);
51         tot=size[to[i]],root=0;
52         get_root(to[i],0);
53         solve(root);
54     }
55 }
56 inline void ini(){
57     memset(vis,0,sizeof(vis));
58     memset(head,0,sizeof(head));
59     memset(ne,0,sizeof(ne));
60     memset(to,0,sizeof(to));
61     memset(v,0,sizeof(v));
62     memset(size,0,sizeof(size));
63     memset(ma,0,sizeof(ma));
64     size[0]=ma[0]=INF,root=0,tot=n,ans=0,cnt=0,num=0;
65 }
66 int main(){
67     while(~scanf("%d",&n)){
68         ini();
69         register int f,t,w;
70         for(register int i=1;i<n;i++){
71             scanf("%d%d%d",&f,&t,&w);
72             add(f,t,w),add(t,f,w);
73         }
74         scanf("%d",&k);
75         get_root(1,0);
76         solve(root);
77         printf("%d\n",ans);
78     }
79 }

猜你喜欢

转载自www.cnblogs.com/Fang-Hao/p/9214985.html