Tree
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和一棵树,求树上有多少点对之间的距离满足小于等于k。
据说是点分治~
那么,点分治大概就是,每次找到一棵树的重心,并把它的子树递归相同处理~
简单的说,正如其名,对点进行分治~
对于一棵树上的路径,只有两种情况:经过根和不经过根。
那么,每次递归到一个节点,只要算出经过根的路径满足要求的个数,就可以了~
于是,递归到一个子树就对其所属点进行dfs求相对深度。
接着对每对点用这个深度互相求满足要求的个数~
因为排了序,所以自然只需要一个左右端点扫描一遍便可O(子树大小)算答案。
然而根据这个根节点求出来的未必是真实路径~
因为未必是LCA,不是最短的~
所以,再对每棵子树以当前根的相对深度求一遍并容斥减去就是我们上面要求的答案了~
最后递归到底,累加答案即可~
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
const int N=10233;
int n,k,ans,root,size;
int to[N<<1],nxt[N<<1],w[N<<1],beg[N],tot;
int siz[N],dep[N],stk[N<<1],mx[N],top;
bool vis[N];
inline void push(int deep)
{
stk[++top]=deep;
}
inline int maxx(int a,int b){if(a>b)return a;return b;}
inline int read()
{
int x=0;char ch=getchar();
while(ch<'0' || '9'<ch)ch=getchar();
while('0'<=ch && ch<='9')
{
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return x;
}
inline void addedge(int u,int v,int c)
{
to[++tot]=v;
nxt[tot]=beg[u];
w[tot]=c;
beg[u]=tot;
}
inline void add(int u,int v,int c)
{
addedge(u,v,c);
addedge(v,u,c);
}
void getdep(int u,int fa)
{
siz[u]=1;
push(dep[u]);
for(int i=beg[u],v;i;i=nxt[i])
if((v=to[i])!=fa && !vis[v])
{
dep[v]=dep[u]+w[i];
getdep(v,u);
siz[u]+=siz[v];
}
}
void getroot(int u,int fa)
{
siz[u]=1;
mx[u]=0;
for(int i=beg[u],v;i;i=nxt[i])
if((v=to[i])!=fa && !vis[v])
{
getroot(v,u);
mx[u]=maxx(mx[u],siz[v]);
siz[u]+=siz[v];
}
mx[u]=maxx(mx[u],size-siz[u]);
if(mx[u]<mx[root])
root=u;
}
inline int calc(int u,int init=0)
{
top=0;
dep[u]=init;
getdep(u,0);
sort(stk+1,stk+top+1);
int ret=0,l=1,r=top;
while(l<r)
if(stk[l]+stk[r]<=k)
ret+=r-l++;
else
r--;
return ret;
}
void work(int u)
{
ans+=calc(u);
vis[u]=1;
for(int i=beg[u],v;i;i=nxt[i])
if(!vis[v=to[i]])
{
ans-=calc(v,w[i]);
mx[0]=size=siz[v];
getroot(v,root=0);
work(root);
}
}
int main()
{
while((n=read()) && (k=read()))
{
tot=0;
memset(beg,0,sizeof(beg));
memset(vis,0,sizeof(vis));
for(int i=1,u,v,c;i<n;i++)
{
u=read();
v=read();
c=read();
add(u,v,c);
}
mx[0]=size=n;
getroot(1,root=0);
ans=0;
work(root);
printf("%d\n",ans);
}
return 0;
}