POJ 1741 树上点分治
题意:
求树上的距离小于等于K的点对个数
题解:
树分治论文题。
需要者请移步qzc论文~
View Code
1 #include <iostream> 2 #include <cstring> 3 #include <algorithm> 4 #include <cstdio> 5 #include <cstdlib> 6 7 #define N 200000 8 #define M 400000 9 #define INF 0x3f3f3f3f 10 11 using namespace std; 12 13 int head[N],next[M],to[M],len[M]; 14 int sz[N],lim[N],dis[N]; 15 bool vis[N]; 16 int n,cnt,root,tot,mn,md; 17 18 inline void add(int u,int v,int w) 19 { 20 to[cnt]=v; len[cnt]=w; next[cnt]=head[u]; head[u]=cnt++; 21 } 22 23 inline void read() 24 { 25 memset(head,-1,sizeof head); cnt=0; 26 for(int i=1,a,b,c;i<n;i++) 27 { 28 scanf("%d%d%d",&a,&b,&c); 29 add(a,b,c); add(b,a,c); 30 } 31 } 32 33 inline void getsize(int u,int fa) 34 { 35 sz[u]=1; lim[u]=0; 36 for(int i=head[u];~i;i=next[i]) 37 if(to[i]!=fa&&!vis[to[i]]) 38 { 39 getsize(to[i],u); 40 sz[u]+=sz[to[i]]; 41 lim[u]=max(lim[u],sz[to[i]]); 42 } 43 } 44 45 inline void getroot(int p,int u,int fa) 46 { 47 lim[u]=max(lim[u],sz[p]-sz[u]); 48 if(lim[u]<mn) mn=lim[u],root=u; 49 for(int i=head[u];~i;i=next[i]) 50 if(to[i]!=fa&&!vis[to[i]]) getroot(p,to[i],u); 51 } 52 53 inline void getdis(int u,int fa,int d) 54 { 55 for(int i=head[u];~i;i=next[i]) 56 if(to[i]!=fa&&!vis[to[i]]) getdis(to[i],u,d+len[i]); 57 dis[++tot]=d; 58 } 59 60 inline int calc(int u,int fa,int d) 61 { 62 tot=0; 63 getdis(u,fa,d); 64 sort(dis+1,dis+1+tot); 65 int res=0; 66 for(int i=1,j=tot;i<j;i++) 67 { 68 while(i<j&&dis[i]+dis[j]>md) j--; 69 if(i>=j) break; 70 res+=j-i; 71 } 72 return res; 73 } 74 75 inline int getans(int u,int fa) 76 { 77 getsize(u,fa); 78 mn=INF; 79 getroot(fa,u,fa); 80 int rt=root; 81 int res=calc(rt,rt,0); 82 vis[root]=true; 83 for(int i=head[rt];~i;i=next[i]) 84 if(to[i]!=fa&&!vis[to[i]]) 85 { 86 res-=calc(to[i],rt,len[i]); 87 res+=getans(to[i],rt); 88 } 89 return res; 90 } 91 92 inline void go() 93 { 94 memset(vis,0,sizeof vis); 95 printf("%d\n",getans(1,1)); 96 } 97 98 int main() 99 { 100 while(scanf("%d%d",&n,&md),n||md) read(),go(); 101 return 0; 102 }
没有人能阻止我前进的步伐,除了我自己!