zoukankan      html  css  js  c++  java
  • 点分治。。。。。

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

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


  • 相关阅读:
    前端总结挺全面的
    cmd与bat脚本的使用
    Spring控制反转(IoC)的理解
    C# 中迭代器
    URL 分页并排序
    结合Flash上传文件时显示进度条
    C# 语言特性
    where T:new()
    图片缩放特效
    C# 隐藏窗体 ALT+TAb不可见
  • 原文地址:https://www.cnblogs.com/zzmmm/p/6501176.html
Copyright © 2011-2022 走看看