zoukankan      html  css  js  c++  java
  • 树分治之点分治模板总结

    点分治的时间复杂度为O(NlogN)。

    由于每次都是找重心,所以处理完一个大小为N的树后,每个子树的大小最大都为N/2,所以最多分治NlogN层,每层都是N

    所以是O(NlogN)。

    【具体流程】

    1,选取一个点,将无根树变成有根树
     为了使每次的处理最优,我们通常要选取树的重心。
     何为“重心”,就是要保证与此点连接的子树的节点数最大值最小,可以防止被卡。
     重心求法:
      1。dfs一次,算出以每个点为根的子树大小。
      2。记录以每个节点为根的最大子树大小

      3。判断:如果以当前节点为根更优,就更新当前根。

    void getroot(int v,int fa)
    {
        son[v] = 1; f[v] = 0;//f记录以v为根的最大子树的大小 
        for(int i = head[v];i;i=e[i].next)
            if(e[i].to != fa && !vis[e[i].to]) {
                getroot(e[i].to,v);//递归更新 
                son[v] += son[e[i].to];
                f[v] = max(f[v],son[e[i].to]);//比较每个子树 
            }
        f[v] = max(f[v],sum-son[v]);//别忘了以v父节点为根的子树 
        if(f[v] < f[root]) root = v;//更新当前根 
    }
    2、处理连通块中通过根节点的路径。

      (注意,是通过根节点的路径,所以后面要去掉同一子树内部的路径,即去重

    3、标记根节点(相当于处理后,将根节点从子树中删除)。

    4、递归处理当前点为根的每棵子树。

    int solve(int v)
    {
        vis[v] = 1;//标记 
        for(int i = head[v];i;i=e[i].next)
            if(!vis[e[i].to]) {
                root = 0;
                sum = son[e[i].to];
                getroot(e[i].to,v);
                solve(root);//递归处理下一个连通块 
            }
    }
    int main()
    {
        sum = f[0] = n;//初始化 
        root = 0;
        getroot(1,0);//找重心 
        solve(root);//点分治 
    }


  • 相关阅读:
    前世今生:Hive、Shark、spark SQL
    spark streaming 6: BlockGenerator、RateLimiter
    spark streaming 5: InputDStream
    spark streaming 4: DStreamGraph JobScheduler
    常见css水平自适应布局
    js动态加载以及确定加载完成的代码
    如何判断css是否加载完成
    翻书特效
    jquery 事件冒泡的介绍以及如何阻止事件冒泡
    phonegap之android原生日历调用
  • 原文地址:https://www.cnblogs.com/vocaloid01/p/9514113.html
Copyright © 2011-2022 走看看