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.
裸的点分治。
代码如下:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define maxn 10006
using namespace std;
int n,K,tot,core,Min,sum,ans,lnk[maxn],nxt[maxn*2],son[maxn*2],w[maxn*2],num[maxn],deep[maxn],d[maxn],f[maxn];
bool vis[maxn];
void add(int x,int y,int z){
nxt[++tot]=lnk[x];son[tot]=y;w[tot]=z;lnk[x]=tot;
}
void get_core(int x,int fa){
num[x]=1;f[x]=0;
for(int j=lnk[x];j;j=nxt[j]) if((son[j]!=fa)&&(vis[son[j]])){
get_core(son[j],x);
num[x]+=num[son[j]];f[x]=max(f[x],num[son[j]]);
}
f[x]=max(f[x],sum-num[x]);
if(f[x]<Min)Min=f[x],core=x;
}
void get_deep(int x,int fa){
deep[++deep[0]]=d[x];
for(int j=lnk[x];j;j=nxt[j]) if((fa!=son[j])&&(vis[son[j]])){
d[son[j]]=d[x]+w[j];
get_deep(son[j],x);
}
}
int cal(int x,int now){
d[x]=now;deep[0]=0;int s=0;
get_deep(x,x);
sort(deep+1,deep+1+deep[0]);
int i=1,j=deep[0];
while(i<j){
while((i<j)&&(deep[i]+deep[j]>K))j--;
s+=j-(i++);
}
return s;
}
void dfs(int x){
vis[x]=0;ans+=cal(x,0);
for(int j=lnk[x];j;j=nxt[j]) if(vis[son[j]]){
ans-=cal(son[j],w[j]);sum=num[son[j]];
Min=1e9;get_core(son[j],son[j]);
dfs(core);
}
}
int _read(){
int sum=0;char ch=getchar();
while(!(ch>='0'&&ch<='9'))ch=getchar();
while(ch>='0'&&ch<='9')sum=sum*10+ch-48,ch=getchar();
return sum;
}
int main(){
freopen("tree_divide.in","r",stdin);
freopen("tree_divide.out","w",stdout);
n=_read();K=_read();
while(n||K){
tot=0;memset(lnk,0,sizeof(lnk));memset(vis,1,sizeof(vis));
for(int i=1,x,y,z;i<n;i++)x=_read(),y=_read(),z=_read(),add(x,y,z),add(y,x,z);
Min=1e9;sum=n;get_core(1,1);ans=0;
dfs(core);
printf("%d\n",ans);
n=_read();K=_read();
}
return 0;
}