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 }
原文地址:https://www.cnblogs.com/proverbs/p/2868721.html