「POJ1741」Tree

点分治

感觉像线性数据结构上的二分

或者说线性数据结构上的二分就是点分治的特殊情况

 1 #include<cstdio> 
 2 #include<iostream>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 const int N=10010,oo=INT_MAX;
 7 int n,maxd,ans;
 8 struct Edge{
 9     int to,len,nxt;
10     Edge(int _to=0,int _len=0,int _nxt=0):to(_to),len(_len),nxt(_nxt){}
11 }edge[N<<1];
12 int last[N],edge_tot;
13 int siz[N],root,f[N],tot,dep[N],dep_tot;
14 bool vis[N];
15 void add_edge(int f,int t,int l){
16     edge[++edge_tot]=Edge(t,l,last[f]);
17     last[f]=edge_tot;
18     return;
19 }
20 void getroot(int k,int fa){
21     siz[k]=1,f[k]=0;
22     for(int i=last[k];i;i=edge[i].nxt){
23         if(edge[i].to==fa||vis[edge[i].to]) continue;
24         getroot(edge[i].to,k);
25         siz[k]+=siz[edge[i].to];
26         f[k]=max(f[k],siz[edge[i].to]);
27     }
28     f[k]=max(f[k],tot-siz[k]);
29     if(f[k]<f[root]) root=k;
30     return;
31 }
32 void dfs(int k,int fa,int d){
33     dep[++dep_tot]=d;
34     for(int i=last[k];i;i=edge[i].nxt){
35         if(edge[i].to==fa||vis[edge[i].to]) continue;
36         dfs(edge[i].to,k,d+edge[i].len);
37     }
38     return;
39 }
40 int calc(int k,int d){
41     dep_tot=0;dfs(k,0,d);
42     sort(dep+1,dep+dep_tot+1);
43     int l=1,r=dep_tot,res=0;
44     for(l;l<r;l++){
45         while(l<r&&dep[r]+dep[l]>maxd) r--;
46         res+=r-l;
47     }
48     return res;
49 }
50 void work(int k){
51     vis[k]=1;
52     ans+=calc(k,0);
53     for(int i=last[k];i;i=edge[i].nxt){
54         if(vis[edge[i].to]) continue;
55         ans-=calc(edge[i].to,edge[i].len);
56         tot=siz[edge[i].to],root=0; //某些情况求出的并不是重心,但要完全求出正确的重心很可能要花费更多的时间 
57         getroot(edge[i].to,k);
58         work(root);
59     }
60     return;
61 }
62 inline void reset(){
63     memset(last,0,sizeof(last));
64     memset(vis,0,sizeof(vis));
65     ans=edge_tot=0;
66 }
67 void solve(){
68     int t1,t2,t3;
69     if(!n) exit(0);
70     for(int i=1;i<n;i++){scanf("%d%d%d",&t1,&t2,&t3);add_edge(t1,t2,t3);add_edge(t2,t1,t3);}
71     root=0,tot=n;
72     getroot(1,0);
73     work(root);
74     printf("%d
",ans);
75     reset();
76     return; 
77 }
78 int main(){
79     f[0]=oo;
80     while(scanf("%d%d",&n,&maxd)) solve();
81     return 0;
82 }
原文地址:https://www.cnblogs.com/mycups/p/8527919.html