点分治。。。。。

点分治,就是在树上分治,讲得很高大上。。。。。。。。

实际上就是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
",ans);
  }
  return 0;
}


原文地址:https://www.cnblogs.com/zzmmm/p/6501176.html