去年这个时候就做这道题了 那个时候完全不懂
今天重新来学了一下点分治 发现自己很多不会
没有照着别人的程序打点分治的时候思路很乱 可能是自己太弱了
后来看了黄学长的代码发现有些东西我打的太复杂了。。。。
然后我就像到了一个新世界
每次都去找中心就好了。。。。
#include<cstdio> #include<iostream> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; char c; bool flag; inline void read(int &a) { a=0,flag=false;do c=getchar();while(c!='-'&&(c<'0'||c>'9')); if(c=='-')flag=true,c=getchar(); while(c<='9'&&c>='0')a=(a<<3)+(a<<1)+c-'0',c=getchar(); if(flag)a=-a; } int root; struct Chain{Chain *next;int u,len;Chain(){next=NULL;}}*Head[100001]; bool choose[10001]; int sum; int Max[100001],son[100001]; void Get_Root(int u,int fa) { son[u]=1; Max[u]=0; for(Chain *tp=Head[u];tp;tp=tp->next) { if(tp->u==fa||choose[tp->u])continue; Get_Root(tp->u,u); son[u]+=son[tp->u]; Max[u]=max(Max[u],son[tp->u]); } Max[u]=max(Max[u],sum-son[u]); if(Max[u]<Max[root])root=u; } int deep[100001]; inline void addside(int a,int b,int len) { Chain *tp=new Chain; tp->u=b,tp->len=len,tp->next=Head[a]; Head[a]=tp; swap(a,b); tp=new Chain; tp->u=b,tp->len=len,tp->next=Head[a]; Head[a]=tp; } int D[100001]; inline void De(int u,int fa) { for(Chain *tp=Head[u];tp;tp=tp->next) if(tp->u!=fa&&!choose[tp->u]) D[tp->u]=D[u]+tp->len,deep[++deep[0]]=D[tp->u],De(tp->u,u); } int k; int Sol_dep(int u,int delta) { int res=0; deep[0]=0; D[u]=deep[++deep[0]]=delta; De(u,u); sort(deep+1,deep[0]+deep+1); int l=1,r=deep[0]; while(l<r) { if(deep[l]+deep[r]>k) r--; else res+=r-l,l++; } return res; } int ans; int Div(int u) { ans+=Sol_dep(u,0); choose[u]=true; for(Chain *tp=Head[u];tp;tp=tp->next) { if(choose[tp->u])continue; ans-=Sol_dep(tp->u,tp->len); sum=son[tp->u]; root=0; Get_Root(tp->u,root); Div(root); } } int main() { int a,b,c; while(true) { int n; read(n),read(k); memset(choose,false,sizeof(choose)); if(!n)return 0; for(int i=1;i<=n;i++) Head[i]=NULL; for(int i=1;i<n;i++) { read(a),read(b),read(c),addside(a,b,c); } sum=n;root=0; Max[0]=1<<29; ans=0; Get_Root(1,0); Div(root); printf("%d\n",ans); } return 0; }