第一道点分治的题目,感觉代码难写hhh,大概思路就是染色法+双指针模拟+分治吧~//..
#include <bits/stdc++.h> using namespace std; const int N=4e4+40; struct node{ int to,val; }; vector<node>G[N]; int root,color[N],f[N],dp[N],sum,vis[N],ans,siz[N],dis[N],heap[N],id,k,n; bool cmp(int a,int b) { return dis[a]<dis[b]; } void f_dis(int u,int pre) { // puts("1"); heap[++id]=u; color[u]=color[pre];f[color[u]]++; for(int i=0;i<G[u].size();i++) { int v=G[u][i].to; if(vis[v]||v==pre) continue; dis[v]=G[u][i].val+dis[u]; f_dis(v,u); } } int cal(int u)//计算以这个根的分治数. { //puts("1"); dis[u]=0;id=0;heap[++id]=u; color[u]=u;f[color[u]]=1; for(int i=0;i<(int)G[u].size();i++) { //puts("1"); int v=G[u][i].to; if(vis[v]) continue; dis[v]=G[u][i].val;color[v]=v;f[color[v]]=0; f_dis(v,v); }//puts("1"); sort(heap+1,heap+1+id,cmp); int res=0,l=1,r=id; while(l<r) { while(l<r&&dis[heap[r]]+dis[heap[l]]<=k) { res+=r-l-f[color[heap[l]]]+1; f[color[heap[l]]]--; l++; } f[color[heap[r]]]--; r--; } return res; } void f_root(int u,int pre) { siz[u]=1;dp[u]=0; for(int i=0;i<(int)G[u].size();i++) { int v=G[u][i].to; if(v==pre||vis[v]) continue; f_root(v,u);siz[u]+=siz[v]; dp[u]=max(dp[u],siz[v]); }dp[u]=max(dp[u],sum-siz[u]); if(dp[u]<dp[root]) root=u; } void solve(int u) { vis[u]=1; ans+=cal(u); for(int i=0;i<(int)G[u].size();i++) { int v=G[u][i].to; if(vis[v]) continue; sum=siz[v];dp[0]=n,root=0; f_root(v,root); solve(root); } } int main() { scanf("%d",&n); for(int i=1;i<=n-1;i++) { int u,v,w; scanf("%d%d%d",&u,&v,&w); G[u].push_back({v,w}); G[v].push_back({u,w}); }dp[0]=sum=n;scanf("%d",&k); f_root(1,0); solve(root); printf("%d\n",ans); return 0; }