zoukankan      html  css  js  c++  java
  • BZOJ 1787: [Ahoi2008]Meet 紧急集合

    二次联通门 : BZOJ 1787: [Ahoi2008]Meet 紧急集合

    /*
        BZOJ 1787: [Ahoi2008]Meet 紧急集合
        
        LCA 
        
        树剖预处理Lca
        然后对于要查询的三个点
        分别求出三个lca
        
        接下来的事就比较神奇了 
        手模几组样例后就会发现
        三个lca必定会有两个相同
        
        这样的话那个不相同的那个就是所要求的点(自己画画图, 就会非常清楚的明白)
        然后分别计算三个点到选出的lca的距离就可以了 
         
    */
    #include <cstdio>
    
    #define Max 500097
    
    inline int abs (int a)
    {
        return a > 0 ? a : -a;
    }
    
    inline void swap (int &a, int &b)
    {
        int now = a;
        a = b;
        b = now;
    }
    
    void read (int &now)
    {
        now = 0;
        register char word = getchar ();
        while (word < '0' || word > '9')
            word = getchar ();
        while (word >= '0' && word <= '9')
        {
            now = now * 10 + word - '0';
            word = getchar ();
        }
    }
    
    class Tree_Chain_Lca_Type
    {
        private :
            
            struct Points 
            {
                int size;
                int father;
                int up_chain_point;
                int deep;
            }
            
            point[Max];
            
            int Count;
            
            struct Edges 
            {
                int to;
                int next;
            }
            edge[Max << 2];
            
            int Edge_Count;
            int edge_list[Max];
            
        public :
            
            inline void AddEdge (int from, int to)
            {
                Edge_Count++;
                edge[Edge_Count].to = to;
                edge[Edge_Count].next = edge_list[from];
                edge_list[from] = Edge_Count;
                Edge_Count++;
                edge[Edge_Count].to = from;
                edge[Edge_Count].next = edge_list[to];
                edge_list[to] = Edge_Count;
            }
            
            void Dfs_1 (int now, int father)
            {
                int pos = Count++;
                point[now].father = father;
                point[now].deep = point[father].deep + 1;
                for (int i = edge_list[now]; i; i = edge[i].next)
                    if (edge[i].to != father)
                        Dfs_1 (edge[i].to, now);
                point[now].size = Count - pos;
            }
            
            void Dfs_2 (int now, int chain)
            {
                point[now].up_chain_point = chain;
                int pos = 0;
                for (int i = edge_list[now]; i; i = edge[i].next)
                    if (edge[i].to != point[now].father && point[edge[i].to].size > point[pos].size)
                        pos = edge[i].to;
                if (!pos)
                    return;
                Dfs_2 (pos, chain);
                for (int i = edge_list[now]; i; i = edge[i].next)
                    if (edge[i].to != pos && edge[i].to != point[now].father)
                        Dfs_2 (edge[i].to, edge[i].to);
            }
            
            int Get_Lca (int x, int y)
            {
                while (point[x].up_chain_point != point[y].up_chain_point)
                {
                    if (point[point[x].up_chain_point].deep < point[point[y].up_chain_point].deep)
                        swap (x, y);
                    x = point[point[x].up_chain_point].father;
                }
                return point[x].deep < point[y].deep ? x : y;
            }
            
            int Get_dis (int x, int y)
            {
                int now = Get_Lca (x, y);
                return point[x].deep + point[y].deep - (point[now].deep << 1);
            }
            
            void Clear ()
            {
                Dfs_1 (1, 0);
                Count = 0;
                Dfs_2 (1, 1);
            }
    };
    
    Tree_Chain_Lca_Type Make;
    
    int N, M;
    
    int main (int argc, char *argv[])
    {
        read (N);
        read (M);
        int x, y, z;
        for (int i = 1; i < N; i++)
        {
            read (x);
            read (y);
            Make.AddEdge (x, y); 
        }
        Make.Clear ();  
        int now_1, now_2, now_3;
        int Answer, now;
        while (M--)
        {
            read (x);
            read (y);
            read (z);
            now_1 = Make.Get_Lca (x, y);
            now_2 = Make.Get_Lca (x, z);
            now_3 = Make.Get_Lca (y, z);   
            if (now_1 == now_2)
                now = now_3;
            else if (now_1 == now_3)
                now = now_2;
            else
                now = now_1;
            printf ("%d %d
    ", now, Make.Get_dis (x, now) + Make.Get_dis (y, now) + Make.Get_dis (z, now)); 
        }
        return 0;
    }
  • 相关阅读:
    JavaScript 内置函数有什么?
    cursor(鼠标手型)属性
    用CSS制作箭头的方法
    CSS 的伪元素是什么?
    用CSS创建分页的实例
    CSS 按钮
    网页布局中高度塌陷的解决方法
    CSS 进度条
    DOM导航与DOM事件
    DOM 修改与DOM元素
  • 原文地址:https://www.cnblogs.com/ZlycerQan/p/6850160.html
Copyright © 2011-2022 走看看