码迷,mamicode.com
首页 > 其他好文 > 详细

BZOJ 1787 [Ahoi2008]Meet 紧急集合

时间:2016-01-04 21:04:15      阅读:323      评论:0      收藏:0      [点我收藏+]

标签:

【马上就要期末考试了,这两天再写个几题估计就要滚粗去搞文化课了qaq】

 

拿到这道题很容易能够联想到LCA。。

然而我这个大弱智一开始想当然地求了三个点的LCA,然后发现连样例都过不去。。实际上这很显然是错误的,画个图模拟一下样例就知道了。

然后去搜题解。题解说对三个点两两求LCA,在得到的三个LCA中枚举一下集合点即可。。想了一下,似乎确实是这个道理

然而又看到一篇提解说,对三个点两两求LCA得到的三个LCA中,必定至少有两个是相同的,那么集合点就是另外一个(如果三个LCA都相同显然随便哪个都行)。这是为啥呢?我这只蒟蒻没想明白qaq如有神犇路过还请给讲讲,愿闻其详。

 

技术分享
  1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4 
  5 using namespace std;
  6 
  7 const size_t Max_N(500050);
  8 const size_t Max_M(1000050);
  9 const int root(1);
 10 
 11 void Get_Val(int &Ret)
 12 {
 13     Ret = 0;
 14     char ch;
 15     while ((ch = getchar()), (ch > 9 || ch < 0))
 16         ;
 17     do
 18     {
 19         (Ret *= 10) += ch - 0;
 20     }
 21     while ((ch = getchar()), (ch >= 0 && ch <= 9));
 22 }
 23 
 24 int N;
 25 
 26 int Total;
 27 int Head[Max_N];
 28 int To[Max_M], Next[Max_M];
 29 
 30 int Father[Max_N], Deep[Max_N];
 31 int Anc[Max_N][25], Sum_Cost[Max_N][25];
 32 
 33 int M;
 34 
 35 inline
 36 void Add_Edge(const int &s, const int &t)
 37 {
 38     ++Total;
 39     To[Total] = t;
 40     Next[Total] = Head[s], Head[s] = Total;
 41 }
 42 
 43 void init()
 44 {
 45     Get_Val(N), Get_Val(M);
 46     int A, B;
 47     for (int i = 1;i != N;++i)
 48     {
 49         Get_Val(A), Get_Val(B);
 50         Add_Edge(A, B), Add_Edge(B, A);
 51     }
 52 }
 53 
 54 void make_tree(const int &u, const int &fa)
 55 {
 56     int v;
 57     for (int i = Head[u];i;i = Next[i])
 58     {
 59         v = To[i];
 60         if (fa != v)
 61         {
 62             Father[v] = u, Deep[v] = Deep[u] + 1;
 63             make_tree(v, u);
 64         }
 65     }
 66 }
 67 
 68 void preprocess()
 69 {
 70     memset(Anc, -1, sizeof(Anc));
 71     for (int i = 1;i <= N;++i)
 72         Anc[i][0] = Father[i], Sum_Cost[i][0] = 1;
 73     for (int j = 1;(1 << j) <= N;++j)
 74         for (int i = 1;i <= N;++i)
 75         {
 76             Anc[i][j] = Anc[Anc[i][j - 1]][j - 1];
 77             Sum_Cost[i][j] = Sum_Cost[i][j - 1] + Sum_Cost[Anc[i][j - 1]][j - 1];
 78         }
 79 }
 80 
 81 int LCA(int p, int q)
 82 {
 83     if (Deep[p] < Deep[q])
 84         swap(p, q);
 85     int log;
 86     for (log = 1;(1 << log) <= Deep[p];++log); --log;
 87     for (int i = log;i >= 0;--i)
 88         if (Deep[p] - (1 << i) >= Deep[q])
 89             p = Anc[p][i];
 90     if (p == q)
 91         return p;
 92     for (int i = log;i >= 0;--i)
 93         if (Anc[p][i] != -1 && Anc[p][i] != Anc[q][i])
 94             p = Anc[p][i], q = Anc[q][i];
 95     return Father[p];
 96 }
 97 
 98 int Cost(int p, int q)
 99 {
100     if (Deep[p] < Deep[q])
101         swap(p, q);
102     int log, Ans(0);
103     for (log = 1;(1 << log) <= Deep[p];++log); --log;
104     for (int i = log;i >= 0;--i)
105         if (Deep[p] - (1 << i) >= Deep[q])
106             Ans += Sum_Cost[p][i], p = Anc[p][i];
107     if (p == q)
108         return Ans;
109     for (int i = log;i >= 0;--i)
110         if (Anc[p][i] != -1 && Anc[p][i] != Anc[q][i])
111         {
112             Ans += Sum_Cost[p][i] + Sum_Cost[q][i];
113             p = Anc[p][i], q = Anc[q][i];
114         }
115     return Ans + 2;
116 }
117 
118 void work()
119 {
120     int A, B, C;
121     int Fa;
122     int x, y, z;
123     while (M--)
124     {
125         Get_Val(A), Get_Val(B), Get_Val(C);
126         x = LCA(A, B), y = LCA(B, C), z = LCA(A, C);
127         if (x == y)
128             Fa = z;
129         else
130             if (x == z)
131                 Fa = y;
132             else
133                 Fa = x;
134         printf("%d %d\n", Fa, Cost(A, Fa) + Cost(B, Fa) + Cost(C, Fa));
135     }    
136 }
137 
138 int main()
139 {
140     init();
141     Deep[root] = 1, make_tree(root, Father[root] = -1);
142     preprocess();
143     work();
144     
145     return 0;
146 }
BZOJ 1787

 

BZOJ 1787 [Ahoi2008]Meet 紧急集合

标签:

原文地址:http://www.cnblogs.com/Created-equal/p/5100215.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!