标签:
【马上就要期末考试了,这两天再写个几题估计就要滚粗去搞文化课了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 }
标签:
原文地址:http://www.cnblogs.com/Created-equal/p/5100215.html