Description
Give a tree with n vertices,each edge has a length(positive integer less than 1001).
Define dist(u,v)=The min distance between node u and v.
Give an integer k,for every pair (u,v) of vertices is called valid if and only if dist(u,v) not exceed k.
Write a program that will count how many pairs which are valid for a given tree.
Input
The input contains several test cases. The first line of each test case contains two integers n, k. (n<=10000) The following n-1 lines each contains three integers u,v,l, which means there is an edge between node u and v of length l.
The last test case is followed by two zeros.
Output
For each test case output the answer on a single line.
Sample Input
5 4
1 2 3
1 3 1
1 4 2
3 5 1
0 0
Sample Output
8
题目大意
求树上长度小于等于k的链有几条
题解
对于这题 可以对这个点延伸出的几棵子树各做一次dfs
记录子树中出现的距离值
对于一棵树的距离值数组
把它排序求一次ans1
再对每棵子树分别求一个自己对自己的ans2
ans1−∑ans2即为最后的ans
代码
#include<cstring>
#include<iostream>
#include<cmath>
#include<cstdio>
#include<algorithm>
#define N 10005
int n,m,k,tot,cnt,rt,ans;
int size[N],ret[2*N],len[2*N],Next[2*N],Head[2*N];
int a[N],dis[N];
bool flag[N];
using namespace std;
inline int read()
{
int x=0;char ch=getchar();
while (ch<'0'||ch>'9') ch=getchar();
while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x;
}
inline void ins(int u,int v,int l)
{
tot++;
ret[tot]=v;
len[tot]=l;
Next[tot]=Head[u];
Head[u]=tot;
}
void find_pre(int u,int f)//预处理
{
size[u]=1;
for (int i=Head[u];i;i=Next[i])
{
int v=ret[i];
if (v!=f&&!flag[v])
{
find_pre(v,u);
size[u]+=size[v];
}
}
}
int find_rt(int u,int f)//寻找重心
{
for (int i=Head[u];i;i=Next[i])
{
int v=ret[i];
if (v!=f&&!flag[v])
{
if (size[v]>size[rt]/2) return find_rt(v,u);
}
}
return u;
}
void dfs(int u,int f)//计算点到根的距离
{
for (int i=Head[u];i;i=Next[i])
{
int v=ret[i];
if (v!=f&&!flag[v])
{
dis[v]=dis[u]+len[i];
a[++cnt]=dis[v];
dfs(v,u);
}
}
}
int cal(int RT,int d)//计算答案
{
dis[RT]=d;
cnt=1;
a[1]=d;
dfs(RT,0);
sort(a+1,a+cnt+1);
int t=0,l,r;
for(l=1,r=cnt;l<r;)
{
if(a[l]+a[r]<=k){t+=r-l;l++;}
else r--;
}
return t;
}
inline void solve(int RT)
{
ans+=cal(RT,0);
flag[RT]=1;
for (int i=Head[RT];i;i=Next[i])
{
int v=ret[i];
if (!flag[v])
{
ans-=cal(v,dis[v]);
find_pre(v,0);
rt=v;
solve(find_rt(rt,0));
}
}
}
int main()
{
n=read();k=read();
while (n!=0&&k!=0)
{
tot=0;
for (int i=1;i<=n;i++)
flag[i]=Head[i]=0;
for (int i=1;i<n;i++)
{
int u=read(),v=read(),l=read();
ins(u,v,l);
ins(v,u,l);
}
find_pre(1,0);
rt=1;
ans=0;
solve(find_rt(1,0));
printf("%d\n",ans);
n=read();k=read();
}
return 0;
}