点分治。。。。。
点分治,就是在树上分治,讲得很高大上。。。。。。。。
实际上就是findroot,answer两个操作;
根据分治的处理方法:分成若干个子问题
因此,在每次dfs都要查找root;据说这样就是优化。。。。
http://poj.org/problem?id=1741
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<queue> #include<algorithm> #include<map> #define MAXX 1000001 #define INF 10000001 using namespace std; int son[MAXX],deep[MAXX],d[MAXX],head[MAXX],tot,f[MAXX],n,k,sum,root,ans; bool vis[MAXX]; struct data{ int nxt,to,w; }edge[MAXX*2]; void add(int from,int too,int ww){edge[++tot].nxt=head[from],head[from]=tot,edge[tot].w=ww,edge[tot].to=too;} void findroot(int num,int fa){ son[num]=1;f[num]=0; for(int i=head[num];i;i=edge[i].nxt)if(fa!=edge[i].to&&!vis[edge[i].to]){ int too=edge[i].to; findroot(too,num); son[num]+=son[too]; f[num]=max(f[num],son[too]); } f[num]=max(f[num],sum-f[num]); if(f[num]<f[root])root=num; } void finddeep(int num,int fa){ deep[++deep[0]]=d[num]; for(int i=head[num];i;i=edge[i].nxt)if(!vis[edge[i].to]&&fa!=edge[i].to){ int too=edge[i].to; d[too]=d[num]+edge[i].w; finddeep(too,num); } } int an(int num,int dis){ deep[0]=0;d[num]=dis; finddeep(num,0); int tot1=0,l=1,r=deep[0]; sort(deep+1,deep+deep[0]+1); while(l<r){ if(deep[r]+deep[l]<=k)tot1+=r-l,l++; else r--; } return tot1; } void answer(int num){ ans+=an(num,0); vis[num]=true; for(int i=head[num];i;i=edge[i].nxt)if(!vis[edge[i].to]){ int too=edge[i].to; ans-=an(too,edge[i].w); sum=son[too]; root=0; findroot(too,0); answer(root); } } int main(){ freopen("1.in","r",stdin); freopen("1.out","w",stdout); while(scanf("%d%d",&n,&k)&&n!=0&&k!=0){ ans=0,tot=0,sum=n; for(int i=1;i<=n;++i)head[i]=0,vis[i]=false; for(int i=1;i<n;++i){ int a,b,c; scanf("%d%d%d",&a,&b,&c),add(a,b,c),add(b,a,c); } root=0;f[root]=INF; findroot(1,0); answer(root); printf("%d\n",ans); } return 0; }