zoukankan      html  css  js  c++  java
  • 树分治和LCA

    树分治

     在树中将树分成几个部分,然后依次解决的方法,这就是一种优化的方法。那么要如何去分治一棵树呢,这里需要一个概念,那就是树的质心
    那么什么是树的质心呢
     指的是让这棵树中的一个点为根,使得这棵树的最大子树的节点数最少
    这就是树的质心。
     那么要怎么找出一个树的质心呢。
        
     假设是这样的一棵树,可见的这棵树含有三个子树,要寻找这棵树的最大子树,那么久需要比较以这颗树中的任意一个节点为根,比较所有的子树的大小,记录最大子树中最小的一个。那么我们要做的就是如何使得能够找出以任意一个节点为根节点的最大子树。
      那么就需要遍历所有的节点,这里首先需要一个存图的数据结构,那么存图又有两种形式,一种是邻接表,一种是邻接矩阵。
    这里的话我们使用邻接表
    void add(int u,int v)
    {
        edge[cnt].to=v;
        edge[cnt].next=head[u];
        head[u]=cnt++;
    }
    这是邻接表的写法,每次传入两个参数,这里的两个参数是指一条边的两个点。将这条边的终点存放在数组edge[i].to中,然后这个数组是一个结构体数组这样的数组还含有另一个参数,而这个参数存储的是这条边是以u为起点的第几条边。
      
     接下来就是让子树1和这棵树剩下的其他子树的和一起比较,比如子树1和子树2和3一起形成的子树比较。这样的比较就是为了排除一种极端的情况,就是当子树1十分的大的时候,比2和3加起来还要大。比较完了之后,

     然后是子树2和子树1比较大小,然后就是上面的子树2和子树1和3比较。
    最后就是2和3 比较。这样一次次的递归下来就能找出最大子树的最小节点数的子树。
     
    #include<cstdio>
    #include<cstring>
    #include<iostream>
     
    using namespace std;
     
    struct node
    {
        int to;
        int next;
    }edge[40005];
     
     
    int son[40005],head[40005];
    int cnt=0,size=0x3f3f3f3f,n,ans;
    int vis[40005];
     
    void add(int u,int v)
    {
        edge[cnt].to=v;
        edge[cnt].next=head[u];
        head[u]=cnt++;
    }
     
    void init()
    {
        cnt=0;
        size=1<<30;
        memset(vis,0,sizeof(vis));
        memset(head,-1,sizeof(head));
    }
     
    int max(int a,int b)
    {
        if(a<b)
        {
            return b;
        }
        else
        {
            return a;
        }
    }
     
    int DFS(int u)
    {
        vis[u]=1;
        son[u]=0;
        int tmp=0;
        for(int i=head[u];~i;i=edge[i].next)
        {
            int x=edge[i].to;
            if(!vis[x])
            {
                DFS(x);
                son[u]+=son[x]+1;
                tmp=max(tmp,son[x]+1);
            }
        }
        tmp=max(tmp,n-son[u]-1);
        if(tmp<size||tmp==size&&u<ans)
        {
            ans=u;
            size=tmp;
        }
    }
     
    int main()
    {
        int T;
        cin>>T;
        while(T--)
        {
            init();
            cin>>n;
            int i,u,v;
            for(i=1;i<n;i++)
            {
               cin>>u>>v;
               add(u,v);
               add(v,u);
            }
            DFS(1);
            printf("%d %d ",ans,size);
        }
        return 0;
    }
  • 相关阅读:
    Optional的使用
    Spring Boot 传送门
    MP(MyBatis-Plus)实现乐观锁更新功能
    实现数据逻辑删除的一种方案
    凹凸技术揭秘 · 基础服务体系 · 构筑服务端技术中枢
    凹凸技术揭秘 · 夸克设计资产 · 打造全矩阵优质物料
    凹凸技术揭秘·羚珑页面可视化·成长蜕变之路
    90%的开发都没搞懂的CI和CD!
    Devops与敏捷二者能否结合?
    优质单元测试的十大标准,你有遵循吗?
  • 原文地址:https://www.cnblogs.com/yewa/p/7243589.html
Copyright © 2011-2022 走看看