[Luogu 3398] 倉鼠找sugar
阿新 • • 發佈:2018-11-06
[Luogu 3398] 倉鼠找sugar
又是 LCA…
前兩天死活寫不過的一個題今天終於順手切了。
思路嘛參考了一樓題解。
就是說,對於 a
, b
, c
, d
四個點,
令 x
= LCA(a, b), y
= LCA(c, d),
兩條路徑有交叉,當且僅當 c
, d
至少一個在 x
的子樹下,且 a
, b
至少一個在 y
的子樹下。
由於我是 HLD 求的 LCA,第一遍 DFS 時順手把子樹大小求了,後邊判斷在不在一棵子屬下的時候就可以很方便了。
就這樣。
#include <algorithm> #include <cstdio> const int MAXN = 100010; int n, q; struct Graph { struct Edge { int to; Edge *next; Edge(int to, Edge* next): to(to), next(next) {} ~Edge(void) { if(next != NULL) delete next; } }*head[MAXN]; Graph(int n) { std :: fill(head + 1, head + n + 1, (Edge*)NULL); } ~Graph(void) { for(int i = 1; i <= n; ++i) delete head[i]; } void AddEdges(int u, int v) { head[u] = new Edge(v, head[u]); head[v] = new Edge(u, head[v]); } }*G; namespace HLD { int num; struct Node { int depth, father, son, top, size, DFN; }s[MAXN]; void DFS1(int u, int k) { s[u].depth = k; s[u].size = 1; int v; for(Graph :: Edge *i = G -> head[u]; i != NULL; i = i -> next) if(!s[v = i -> to].size) { DFS1(v, k + 1); s[u].size += s[v].size; s[v].father = u; if(s[v].size > s[s[u].son].size) s[u].son = v; } } void DFS2(int u, int top) { s[u].top = top; s[u].DFN = ++num; if(s[u].son) DFS2(s[u].son, top); int v; for(Graph :: Edge *i = G -> head[u]; i != NULL; i = i -> next) if(!s[v = i -> to].DFN) DFS2(v, v); } void Init(void) { DFS1(1, 1); DFS2(1, 1); } int LCA(int x, int y) { int a, b; while((a = s[x].top) ^ (b = s[y].top)) if(s[a].depth > s[b].depth) x = s[a].father; else y = s[b].father; return s[x].depth < s[y].depth ? x : y; } bool Range(int x, int y) { return s[x].DFN <= s[y].DFN && s[y].DFN < s[x].DFN + s[x].size; } bool Query(int a, int b, int c, int d) { int x = LCA(a, b), y = LCA(c, d); return (Range(x, c) || Range(x, d)) && (Range(y, a) || Range(y, b)); } } int main(void) { scanf("%d %d", &n, &q); G = new Graph(n); for(int i = 1, u, v; i < n; ++i) { scanf("%d %d", &u, &v); G -> AddEdges(u, v); } HLD :: Init(); for(int i = 1, a, b, c, d; i <= q; ++i) { scanf("%d %d %d %d", &a, &b, &c, &d); puts(HLD :: Query(a, b, c, d) ? "Y" : "N"); } return 0; }
謝謝閱讀。