树的点分治——模板

Posted Troy Ricardo

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了树的点分治——模板相关的知识,希望对你有一定的参考价值。

  1 #define Troy 9/28/2017
  2 
  3 #define inf 0x7fffffff
  4 
  5 #include "cstdio"
  6 #include "cstring"
  7 #include "algorithm"
  8 using std::sort;
  9 
 10 typedef long long ll;
 11 ll ans;
 12 
 13 inline int max(int a,int b){return a>b?a:b;}
 14 inline int min(int a,int b){return a<b?a:b;}
 15 inline int read(){
 16     int s=0,k=1;char ch=getchar();
 17     while(ch<0|ch>9)    ch==-?k=-1:0,ch=getchar();
 18     while(ch>47&ch<=9)    s=s*10+(ch^48),ch=getchar();
 19     return s*k;
 20 }
 21 const int N=10050;
 22 
 23 struct edges {
 24     int v,w;edges *last;
 25 }edge[N<<1],*head[N];int cnt;
 26 inline void push(int u,int v,int w){
 27     edge[++cnt]=(edges){v,w,head[u]};head[u]=edge+cnt;
 28     edge[++cnt]=(edges){u,w,head[v]};head[v]=edge+cnt;
 29 }
 30 bool del[N];int n,K;
 31 int top;bool vis[N];
 32 
 33 inline void clear(){
 34     cnt=0;ans=0;
 35     memset(vis,0,sizeof(vis));
 36     memset(head,0,sizeof(head));
 37 }
 38 
 39 int size[N],heavy[N],root,num,dis[N];
 40 
 41 inline void dfs_size(int x,int fa){
 42     size[x]=1;
 43     heavy[x]=0;
 44     for(edges *i=head[x];i;i=i->last)   if(vis[i->v]||i->v==fa)  continue;
 45     else{
 46         dfs_size(i->v,x);
 47         heavy[x]=max(size[i->v],heavy[x]);
 48         size[x]+=size[i->v];
 49     }
 50 }
 51 
 52 inline void find_root(int tot,int x,int fa){
 53     heavy[x]=max(tot-size[x],heavy[x]);
 54     if(heavy[x]<top)    top=heavy[x],root=x;
 55     for(edges *i=head[x];i;i=i->last){
 56         if(i->v==fa|vis[i->v])  continue;
 57         find_root(tot,i->v,x);
 58     }
 59 }
 60 
 61 inline void dfs_dis(int x,int d,int fa){
 62     dis[num++]=d;
 63     for(edges *i=head[x];i;i=i->last){
 64         if(i->v==fa|vis[i->v])    continue;
 65         dfs_dis(i->v,d+i->w,x);
 66     }
 67 }
 68 
 69 inline ll calc(int x,int d){
 70     ll ret=0;
 71     num=0;
 72     dfs_dis(x,d,x);
 73     sort(dis,dis+num);
 74     int l=0,r=num-1;
 75     while(l<r){
 76         while(l<r&&dis[l]+dis[r]>K) r--;
 77         ret+=r-l;
 78         l++;
 79     }return ret;
 80 }
 81 
 82 inline void solve(int u){
 83     top=inf;
 84     dfs_size(u,u);
 85     find_root(size[u],u,u);
 86     ans+=calc(root,0);
 87     vis[root]=true;
 88     for(edges *i=head[root];i;i=i->last)
 89         if(!vis[i->v]){
 90 
 91             ans-=calc(i->v,i->w);
 92             solve(i->v);
 93         }
 94 }
 95 
 96 int main(){
 97 #ifdef Troy
 98     while(scanf("%d%d",&n,&K)==2&&n&&K){
 99         clear();
100         for(int i=1,u,v,w;i<n;i++){
101             u=read(),v=read(),w=read();
102             push(u,v,w);
103         }
104         solve(1);
105         printf("%lld\n",ans);
106     }
107 #endif
108 }
109 /*
110 5 4
111 1 2 3
112 1 3 1
113 1 4 2
114 3 5 1
115 0 0
116 */

 

以上是关于树的点分治——模板的主要内容,如果未能解决你的问题,请参考以下文章

树的点分治讲解

POJ - 1655 (点分治-树的重心)

模板点分治

poj 1741 Tree(树的点分治)

BZOJ 2152 聪聪可可 | 树的点分治

HDU4812 D Tree(树的点分治)