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 }

 

 

你可能感兴趣的:(poj)