题面:
思路:
树上点对信息?
点分治啊!
照例处理联通块信息,然后再减掉儿子里面重复的
至于每个联通块的信息,就是把每个点到父亲的距离,小于k的放到一个数组里面,排个序,两头双指针扫一遍即可,O(nlogn)
再加上递归层数logn,总效率O(nlognlogn)
Code:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 inline int read(){ 7 int re=0,flag=1;char ch=getchar(); 8 while(ch>‘9‘||ch<‘0‘){ 9 if(ch==‘-‘) flag=-1; 10 ch=getchar(); 11 } 12 while(ch>=‘0‘&&ch<=‘9‘) re=(re<<1)+(re<<3)+ch-‘0‘,ch=getchar(); 13 return re*flag; 14 } 15 int n,m,cnt,root,sum,ans=0,first[10010]; 16 int d[10010],dis[10010],siz[10010],son[10010]; 17 bool vis[10010]; 18 struct edge{ 19 int to,next,w; 20 }a[20010]; 21 inline void add(int u,int v,int w){ 22 a[++cnt]=(edge){v,first[u],w};first[u]=cnt; 23 a[++cnt]=(edge){u,first[v],w};first[v]=cnt; 24 } 25 void init(){ 26 cnt=0;ans=0;memset(first,-1,sizeof(first)); 27 memset(siz,0,sizeof(siz));memset(son,0,sizeof(son)); 28 memset(dis,0,sizeof(dis));memset(vis,0,sizeof(vis)); 29 } 30 inline int _max(int l,int r){return (l>r)?l:r;} 31 inline int _min(int l,int r){return (l<r)?l:r;} 32 void getroot(int u,int f){ 33 //cout<<"getroot "<<u<<" "<<f<<"\n"; 34 int i,v; 35 siz[u]=1;son[u]=0; 36 for(i=first[u];~i;i=a[i].next){ 37 v=a[i].to; 38 if(v==f||vis[v]) continue; 39 getroot(v,u); 40 siz[u]+=siz[v];son[u]=_max(son[u],siz[v]); 41 } 42 son[u]=_max(son[u],sum-siz[u]); 43 if(son[u]<son[root]) root=u; 44 //cout<<"finish getroot "<<u<<" "<<root<<"\n"; 45 } 46 void getdis(int u,int f){ 47 dis[++dis[0]]=d[u]; 48 int i,v; 49 for(i=first[u];~i;i=a[i].next){ 50 v=a[i].to; 51 if(v==f||vis[v]) continue; 52 d[v]=d[u]+a[i].w; 53 getdis(v,u); 54 } 55 } 56 int calc(int u,int dd){ 57 dis[0]=0;d[u]=dd; 58 getdis(u,0); 59 sort(dis+1,dis+dis[0]+1); 60 int l=1,r=dis[0],re=0; 61 while(l<r){ 62 if(dis[l]+dis[r]<=m) re+=r-l,l++; 63 else r--; 64 } 65 return re; 66 } 67 void dfs(int u){ 68 //cout<<"dfs "<<u<<"\n"; 69 int i,v;vis[u]=1; 70 ans+=calc(u,0); 71 for(i=first[u];~i;i=a[i].next){ 72 v=a[i].to; 73 if(vis[v]) continue; 74 ans-=calc(v,a[i].w); 75 sum=siz[v];root=0; 76 getroot(v,0); 77 dfs(root); 78 } 79 } 80 int main(){ 81 //freopen("tree.in","r",stdin); 82 int i,t1,t2,t3; 83 while((n=read())&&(m=read())){ 84 init(); 85 for(i=1;i<n;i++){ 86 t1=read();t2=read();t3=read(); 87 add(t1,t2,t3); 88 } 89 sum=n;root=0;son[0]=n; 90 getroot(1,0); 91 dfs(root); 92 printf("%d\n",ans); 93 } 94 }