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
1 6 13
6 3 9
3 5 7
4 1 3
2 4 20
4 7 2
10
Sample Output
5
HINT
三个月没碰点分治了复习一波,老年选手竟然还能打出来
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define inf 1e8 6 #define ll long long 7 #define M 40010 8 using namespace std; 9 struct point{ 10 int next,to,dis; 11 }e[M<<1]; 12 int head[M],dis[M],maxsize[M],size[M]; 13 bool vis[M]; 14 int n,num,k,S,maxn,root; 15 ll ans; 16 void add(int from,int to,int dis) 17 { 18 e[++num].next=head[from]; 19 e[num].to=to; 20 e[num].dis=dis; 21 head[from]=num; 22 } 23 void getroot(int x,int fa) 24 { 25 size[x]=1; maxsize[x]=0; 26 for(int i=head[x];i;i=e[i].next) 27 { 28 int to=e[i].to; 29 if(vis[to]||to==fa) continue; 30 getroot(to,x); 31 maxsize[x]=max(maxsize[x],size[to]); 32 size[x]+=size[to]; 33 } 34 maxsize[x]=max(S-size[x],maxsize[x]); 35 if(maxsize[x]<maxn) maxn=maxsize[x],root=x; 36 } 37 void getdis(int x,int fa,int len) 38 { 39 dis[++num]=len; 40 for(int i=head[x];i;i=e[i].next) 41 { 42 int to=e[i].to; 43 if(vis[to]||to==fa) continue; 44 getdis(to,x,len+e[i].dis); 45 } 46 return; 47 } 48 int cal(int x,int len) 49 { 50 num=0; 51 memset(dis,0,sizeof(dis)); 52 getdis(x,0,len); 53 sort(dis+1,dis+1+num); 54 int l=1,r=num,tot=0; 55 while(l<=r) 56 { 57 if(dis[l]+dis[r]<=k) tot+=r-l,l++; 58 else r--; 59 } 60 return tot; 61 } 62 void solve(int x) 63 { 64 ans+=cal(x,0); 65 vis[x]=true; 66 for(int i=head[x];i;i=e[i].next) 67 { 68 int to=e[i].to; 69 if(vis[to]) continue; 70 ans-=cal(to,e[i].dis); 71 S=size[to]; root=0; maxn=inf; 72 getroot(to,0); solve(root); 73 } 74 } 75 int main() 76 { 77 scanf("%d",&n); 78 for(int i=1;i<=n-1;i++) 79 { 80 int x,y,z; 81 scanf("%d%d%d",&x,&y,&z); 82 add(x,y,z); add(y,x,z); 83 } 84 scanf("%d",&k); 85 maxn=inf; S=n; getroot(1,0); 86 solve(root); 87 printf("%lld",ans); 88 return 0; 89 }