[poj1741] tree [点分治]

题面:

传送门

思路:

树上点对信息?

点分治啊!

照例处理联通块信息,然后再减掉儿子里面重复的

至于每个联通块的信息,就是把每个点到父亲的距离,小于k的放到一个数组里面,排个序,两头双指针扫一遍即可,O(nlogn)

再加上递归层数logn,总效率O(nlognlogn)

Code:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 inline int read(){
 7     int re=0,flag=1;char ch=getchar();
 8     while(ch>'9'||ch<'0'){
 9         if(ch=='-') flag=-1;
10         ch=getchar();
11     }
12     while(ch>='0'&&ch<='9') re=(re<<1)+(re<<3)+ch-'0',ch=getchar();
13     return re*flag;
14 }
15 int n,m,cnt,root,sum,ans=0,first[10010];
16 int d[10010],dis[10010],siz[10010],son[10010];
17 bool vis[10010];
18 struct edge{
19     int to,next,w;
20 }a[20010];
21 inline void add(int u,int v,int w){
22     a[++cnt]=(edge){v,first[u],w};first[u]=cnt;
23     a[++cnt]=(edge){u,first[v],w};first[v]=cnt;
24 }
25 void init(){
26     cnt=0;ans=0;memset(first,-1,sizeof(first));
27     memset(siz,0,sizeof(siz));memset(son,0,sizeof(son));
28     memset(dis,0,sizeof(dis));memset(vis,0,sizeof(vis));
29 }
30 inline int _max(int l,int r){return (l>r)?l:r;}
31 inline int _min(int l,int r){return (l<r)?l:r;}
32 void getroot(int u,int f){
33     //cout<<"getroot "<<u<<" "<<f<<"
";
34     int i,v;
35     siz[u]=1;son[u]=0;
36     for(i=first[u];~i;i=a[i].next){
37         v=a[i].to;
38         if(v==f||vis[v]) continue;
39         getroot(v,u);
40         siz[u]+=siz[v];son[u]=_max(son[u],siz[v]);
41     }
42     son[u]=_max(son[u],sum-siz[u]);
43     if(son[u]<son[root]) root=u;
44     //cout<<"finish getroot "<<u<<" "<<root<<"
";
45 }
46 void getdis(int u,int f){
47     dis[++dis[0]]=d[u];
48     int i,v;
49     for(i=first[u];~i;i=a[i].next){
50         v=a[i].to;
51         if(v==f||vis[v]) continue;
52         d[v]=d[u]+a[i].w;
53         getdis(v,u);
54     }
55 }
56 int calc(int u,int dd){
57     dis[0]=0;d[u]=dd;
58     getdis(u,0);
59     sort(dis+1,dis+dis[0]+1);
60     int l=1,r=dis[0],re=0;
61     while(l<r){
62         if(dis[l]+dis[r]<=m) re+=r-l,l++;
63         else r--;
64     }
65     return re;
66 }
67 void dfs(int u){
68     //cout<<"dfs "<<u<<"
";
69     int i,v;vis[u]=1;
70     ans+=calc(u,0);
71     for(i=first[u];~i;i=a[i].next){
72         v=a[i].to;
73         if(vis[v]) continue;
74         ans-=calc(v,a[i].w);
75         sum=siz[v];root=0;
76         getroot(v,0);
77         dfs(root);
78     }
79 }
80 int main(){
81     //freopen("tree.in","r",stdin);
82     int i,t1,t2,t3;
83     while((n=read())&&(m=read())){
84         init();
85         for(i=1;i<n;i++){
86             t1=read();t2=read();t3=read();
87             add(t1,t2,t3);
88         }
89         sum=n;root=0;son[0]=n;
90         getroot(1,0);
91         dfs(root);
92         printf("%d
",ans);
93     }
94 }
原文地址:https://www.cnblogs.com/dedicatus545/p/8456732.html