学习了一下点分治
POJ 1741(由于poj不支持c++11和bits,改一下即可ac)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 struct edge 5 { 6 int to,val; 7 edge(int a,int b) 8 {to=a,val=b;} 9 }; 10 const int maxn=10005; 11 vector<edge>G[maxn]; 12 int sz[maxn],f[maxn],used[maxn],rt; 13 int n,size,k; 14 ll ans; 15 void getrt(int u,int fa) 16 { 17 f[u]=0; 18 sz[u]=1; 19 for(auto i:G[u]) 20 { 21 int v=i.to; 22 if(v==fa || used[v]) continue; 23 getrt(v,u); 24 sz[u]+=sz[v]; 25 f[u]=max(f[u],sz[v]); 26 } 27 f[u]=max(f[u],size-sz[u]); 28 if(f[u]<f[rt]) rt=u; 29 } 30 int d[maxn]; 31 vector<int>tmp; 32 void dfs(int u,int fa) 33 { 34 for(auto i:G[u]) 35 { 36 int v=i.to,val=i.val; 37 if(v==fa || used[v]) continue; 38 d[v]=d[u]+val; 39 tmp.push_back(d[v]); 40 dfs(v,u); 41 } 42 } 43 int calc(int u,int dep) 44 { 45 tmp.clear(); 46 d[u]=dep; 47 tmp.push_back(d[u]); 48 dfs(u,0); 49 sort(tmp.begin(),tmp.end()); 50 int ret=0; 51 for(int l=0,r=tmp.size()-1;l<tmp.size() && l<r;l++) 52 { 53 if(2*tmp[l]>k) break; 54 while(tmp[l]+tmp[r]>k) r--; 55 if(l>=r) break; 56 ret+=r-l; 57 } 58 return ret; 59 } 60 void divide(int now) 61 { 62 ans+=calc(now,0); 63 used[now]=1; 64 for(auto i:G[now]) 65 { 66 int v=i.to,val=i.val; 67 if(used[v]) continue; 68 ans-=calc(v,val); 69 rt=0; 70 size=sz[v]; 71 getrt(v,0); 72 divide(rt); 73 } 74 } 75 void init() 76 { 77 f[0]=1e9+7; 78 for(int i=1;i<=n;i++) used[i]=0,G[i].clear(); 79 rt=ans=0; 80 } 81 int main() 82 { 83 #ifdef amori 84 freopen("in.txt","r",stdin); 85 #endif // amori 86 while(~scanf("%d%d",&n,&k)) 87 { 88 if(!n && !k) break; 89 init(); 90 for(int i=1;i<n;i++) 91 { 92 int u,v,w; 93 scanf("%d%d%d",&u,&v,&w); 94 G[u].push_back(edge(v,w)); 95 G[v].push_back(edge(u,w)); 96 } 97 getrt(1,0); 98 divide(rt); 99 printf("%d\n",ans); 100 } 101 }
注意事项:初始化时设f[0]为inf,每次重新获取重心(getrt)的时候,将rt初始化为0,size初始化为子树的大小(sz[v])。