点分治
感觉像线性数据结构上的二分
或者说线性数据结构上的二分就是点分治的特殊情况
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 const int N=10010,oo=INT_MAX; 7 int n,maxd,ans; 8 struct Edge{ 9 int to,len,nxt; 10 Edge(int _to=0,int _len=0,int _nxt=0):to(_to),len(_len),nxt(_nxt){} 11 }edge[N<<1]; 12 int last[N],edge_tot; 13 int siz[N],root,f[N],tot,dep[N],dep_tot; 14 bool vis[N]; 15 void add_edge(int f,int t,int l){ 16 edge[++edge_tot]=Edge(t,l,last[f]); 17 last[f]=edge_tot; 18 return; 19 } 20 void getroot(int k,int fa){ 21 siz[k]=1,f[k]=0; 22 for(int i=last[k];i;i=edge[i].nxt){ 23 if(edge[i].to==fa||vis[edge[i].to]) continue; 24 getroot(edge[i].to,k); 25 siz[k]+=siz[edge[i].to]; 26 f[k]=max(f[k],siz[edge[i].to]); 27 } 28 f[k]=max(f[k],tot-siz[k]); 29 if(f[k]<f[root]) root=k; 30 return; 31 } 32 void dfs(int k,int fa,int d){ 33 dep[++dep_tot]=d; 34 for(int i=last[k];i;i=edge[i].nxt){ 35 if(edge[i].to==fa||vis[edge[i].to]) continue; 36 dfs(edge[i].to,k,d+edge[i].len); 37 } 38 return; 39 } 40 int calc(int k,int d){ 41 dep_tot=0;dfs(k,0,d); 42 sort(dep+1,dep+dep_tot+1); 43 int l=1,r=dep_tot,res=0; 44 for(l;l<r;l++){ 45 while(l<r&&dep[r]+dep[l]>maxd) r--; 46 res+=r-l; 47 } 48 return res; 49 } 50 void work(int k){ 51 vis[k]=1; 52 ans+=calc(k,0); 53 for(int i=last[k];i;i=edge[i].nxt){ 54 if(vis[edge[i].to]) continue; 55 ans-=calc(edge[i].to,edge[i].len); 56 tot=siz[edge[i].to],root=0; //某些情况求出的并不是重心,但要完全求出正确的重心很可能要花费更多的时间 57 getroot(edge[i].to,k); 58 work(root); 59 } 60 return; 61 } 62 inline void reset(){ 63 memset(last,0,sizeof(last)); 64 memset(vis,0,sizeof(vis)); 65 ans=edge_tot=0; 66 } 67 void solve(){ 68 int t1,t2,t3; 69 if(!n) exit(0); 70 for(int i=1;i<n;i++){scanf("%d%d%d",&t1,&t2,&t3);add_edge(t1,t2,t3);add_edge(t2,t1,t3);} 71 root=0,tot=n; 72 getroot(1,0); 73 work(root); 74 printf("%d ",ans); 75 reset(); 76 return; 77 } 78 int main(){ 79 f[0]=oo; 80 while(scanf("%d%d",&n,&maxd)) solve(); 81 return 0; 82 }