/*

1468: Tree

Time Limit: 10 Sec  Memory Limit: 64 MB
Submit: 774  Solved: 412
[Submit][Status][Discuss]

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*/

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
int head[40008],next[80008],v[80006],u[80006],n,m,son[40008],zi[40008],f[40008];
int cnt,sum,root,d[40008],sum1,d1[40008],k;
void bian(int a1,int a2,int a3)
{
cnt++;
next[cnt]=head[a1];
head[a1]=cnt;
u[cnt]=a2;
v[cnt]=a3;
return;
}
void dfs1(int a1,int a2)
{
zi[a1]=0;
son[a1]=1;
for(int i=head[a1];i;i=next[i])
if(u[i]!=a2&&!f[u[i]])
{
dfs1(u[i],a1);
son[a1]+=son[u[i]];
zi[a1]=max(zi[a1],son[u[i]]);
}
zi[a1]=max(zi[a1],sum-son[a1]);
if(zi[a1]<zi[root])
root=a1;
}
void dfs2(int a1,int a2)
{
d[++d[0]]=d1[a1];
for(int i=head[a1];i;i=next[i])
{
if(u[i]==a2||f[u[i]])continue;
d1[u[i]]=d1[a1]+v[i];
dfs2(u[i],a1);
}
}
int gal(int a1,int a2)
{
d1[a1]=a2;
d[0]=0;
dfs2(a1,0);
sort(d+1,d+d[0]+1);
int t=0,l,r;
for(l=1,r=d[0];l<r;)
{
if(d[l]+d[r]<=k){t+=r-l;l++;}
else r--;
}
return t;
}
void work(int a1)
{
sum1+=gal(a1,0);
f[a1]=1;
for(int i=head[a1];i;i=next[i])
{
if(f[u[i]])
continue;
sum1-=gal(u[i],v[i]);
root=0;
sum=son[u[i]];
dfs1(u[i],0);
work(root);
}
}
int main()
{
scanf("%d",&n);
for(int i=0;i<n-1;i++)
{
int a1,a2,a3;
scanf("%d%d%d",&a1,&a2,&a3);
bian(a1,a2,a3);
bian(a2,a1,a3);
}
scanf("%d",&k);
zi[0]=sum=n;
dfs1(1,0);
work(root);
printf("%d\n",sum1);
return 0;
}

posted on 2016-01-19 07:37  xiyuedong  阅读(101)  评论(0编辑  收藏  举报