点分治。。。。。

来源:互联网 发布:电脑版淘宝 编辑:程序博客网 时间:2024/04/30 07:29

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

实际上就是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 10000001using 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;}


0 0