Skip to main content

LCA

BOJ 35288 Designant.

·473 words·3 mins
๐Ÿ“ ๋ฌธ์ œ ์ •๋ณด # ๋งํฌ: https://www.acmicpc.net/problem/35288 ๐Ÿง ๊ด€์ฐฐ ๋ฐ ์ ‘๊ทผ # ๋ฌธ์ œ๋ฅผ ์ •๋ฆฌํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค. ํŠธ๋ฆฌ๊ฐ€ ์ฃผ์–ด์ง„๋‹ค. ๊ฐ„์„ ์„ $K$๊ฐœ ์ง€์›Œ์„œ ํฌ๋ ˆ์ŠคํŠธ๋กœ ๋งŒ๋“ ๋‹ค. ํฌ๋ ˆ์ŠคํŠธ๋ฅผ ์ž˜ ํ•ฉ์ณ์„œ ํŠธ๋ฆฌ์˜ ์ง€๋ฆ„์ด ์ตœ์†Œ๊ฐ€ ๋˜๋„๋ก ํ•˜์ž. ํฌ๋ ˆ์ŠคํŠธ๋ฅผ ์ž˜ ํ•ฉ์น˜๋Š” ๋ฌธ์ œ๋Š” ๋นŒ๋ผ๋ด‰์œผ๋กœ ์œ ๋ช…ํ•˜๋‹ค. ์ด ๋ฌธ์ œ์— ๋”ฐ๋ฅด๋ฉด, ์„ธ๊ฐœ ์ด์ƒ์˜ ํŠธ๋ฆฌ๋ฅผ ํ•ฉ์น  ๋•Œ, ๊ฐ€์žฅ ๊ธด ํŠธ๋ฆฌ์˜ ์ง€๋ฆ„ ์„ธ๊ฐœ๋ฅผ $a \geq b \geq c$ ๋ผ๊ณ  ํ•˜๋ฉด ๊ทธ ๊ฒฐ๊ณผ๋Š” $\max(a, \lceil\frac{a}{2}\rceil + \lceil\frac{b}{2}\rceil + 1, \lceil\frac{b}{2}\rceil + \lceil\frac{c}{2}\rceil + 2)$ ๊ฒฐ๊ณผ๋Š” ์œ„์™€ ๊ฐ™๊ณ , ์ด๋Š” ์ƒˆ๋กœ ๋งŒ๋“  ๊ฐ„์„ ์„ $0, 1, 2$๊ฐœ ์ด์šฉํ•˜๋Š” ๊ฒฝ๋กœ์ค‘ ๊ฐ€์žฅ ๊ธด๊ฒƒ๊ณผ ๊ฐ™๋‹ค. ๊ทธ๋ฆฌ๋””ํ•˜๊ฒŒ ๊ฐ€์žฅ ๊ธด ์ง€๋ฆ„์˜ ์ค‘์‹ฌ์— ๋‹ค๋ฅธ ์ค‘์‹ฌ๋“ค์„ ์ด์€ ๋ชจ์–‘์—์„œ ๋‚˜์˜จ ๊ฒฐ๊ณผ์ด๋‹ค. ๊ทธ๋ ‡๋‹ค๋ฉด ํŠธ๋ฆฌ๋ฅผ ๋น ๋ฅด๊ฒŒ ์ชผ๊ฐœ์„œ ์ง€๋ฆ„๋งŒ ๋น ๋ฅด๊ฒŒ ๊ณ„์‚ฐํ•  ์ˆ˜ ์žˆ์œผ๋ฉด ๋˜๋Š” ๊ฒƒ ๊ฐ™๋‹ค. ์ด๊ฑธ ์–ด๋–ป๊ฒŒ ํ•  ์ˆ˜ ์žˆ์„๊นŒ? ์˜ˆ์ œ 1๋ฒˆ์˜ ํŠธ๋ฆฌ๋ฅผ ETT๋ฅผ ํ•˜๋ฉด์„œ ๊ทธ๋ ค๋ณด์ž. ![[Drawing 2026-02-25 22.49.23.excalidraw.png]] ๊ทธ๋ฆฌ๊ณ  ์„ธ๋ฒˆ์งธ ์ฟผ๋ฆฌ๋ฅผ ์ƒ๊ฐํ•ด๋ณด์ž. $(1, 2), (3, 6), (4, 5, 7)$์œผ๋กœ ๋‚˜๋‰˜์–ด์•ผ ํ•˜๋Š”๋””… ETT๋กœ ์ƒ๊ฐํ•˜๋ฉด, $(1, 2, (5, (3, 6), 4, 7))$ ๊ฐ™์€ ๋А๋‚Œ์œผ๋กœ ๊ทธ๋ฃน์ง€์–ด์ง€๋Š”๊ฑด๊ฐ€? ์ž˜ ์ฒ˜๋ฆฌ๋œ ๋ถ€๋ถ„๋“ค์€ ์ƒ๊ด€ ์—†๋Š”๋ฐ, $(5, 4, 7)$๊ฐ™์€๋ฐ์„œ ์ง€๋ฆ„์„ ์–ด๋–ป๊ฒŒ ๊ตฌํ•˜๋ฉด ์ข‹์„์ง€ ๊ฐ์ด ์•ˆ์˜จ๋‹ค. ์ผ๋‹จ ์ €๊ฑธ $(5), (4,7)$ ๋‘ ๋ฉ์–ด๋ฆฌ๋ฅผ ํ•ฉ์น˜๋Š” ์—ฐ์‚ฐ์œผ๋กœ ๋ณด์ž. ์˜ค์ผ๋Ÿฌ ํˆฌ์–ด ํ…Œํฌ๋‹‰์„ ์ ์šฉํ•˜๋ฉด ์—ฐ์† ๊ตฌ๊ฐ„์— ์†ํ•˜๋Š” ๋…ธ๋“œ๋“ค์˜ ์ง€๋ฆ„์€ ์„ธ๊ทธ๋จผํŠธ ํŠธ๋ฆฌ๋กœ ๊ตฌํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ํ•œ๋‹ค. ์ด๊ฑธ ์–ด๋–ป๊ฒŒ ํ•˜๋Š”๊ฑฐ์ง€? ํŠธ๋ฆฌ ๋‘๊ฐœ์˜ ์ง€๋ฆ„์˜ ์–‘๋ ์ ์„ ๊ฐ๊ฐ $(a, b), (c, d)$ ๋ผ๊ณ  ํ• ๋•Œ ๋‘ ํŠธ๋ฆฌ๋ฅผ ํ•ฉ์นœ๊ณณ์—์„œ์˜ ์ง€๋ฆ„์€ $(a, b), (a, c), (a, d), (b, c), (b, d), (c, d)$์ค‘์—์„œ ์กด์žฌํ•œ๋‹ค. ์ด๋ฅผ pull์—ฐ์‚ฐ์œผ๋กœ ์ž˜ ์ •์˜ํ•ด๋ณด์ž. ๊ตฌํ˜„์ด ์ƒ๋‹นํžˆ ์–ด๋ ต๋‹ค.. ๐Ÿ’ป ํ’€์ด # ์ฝ”๋“œ (C++): void solve(){ int N, Q; cin >> N >> Q; vector<vector<int>> links(N+1); vector<pii> edges; rep(i, 0, N-1){ int u, v; cin >> u >> v; links[u].push_back(v); links[v].push_back(u); edges.push_back({u, v}); } auto [ETT_in, ETT_out] = ETT(N, links); vector<int> ETT_inv(N+1); rep(i, 1, N+1) ETT_inv[ETT_in[i]] = i; LCA_Tree = new Tree_LCA(N+1, links); vector<Node> nodes(N+1); rep(i, 1, N+1) nodes[i] = Node(ETT_inv[i], ETT_inv[i], 0); SegmentTreeNode seg(N+1, nodes); vector<int> edge_to_subtree(N-1); rep(i, 0, N-1){ auto [u, v] = edges[i]; if(LCA_Tree->depth[u] < LCA_Tree->depth[v]) swap(u, v); edge_to_subtree[i] = u; } while(Q--){ int K; cin >> K; vector<int> cuts(K); rep(i, 0, K) cin >> cuts[i]; vector<Node> Query_nodes; vector<pair<int, bool>> events; // {ETT_idx, is_end} for(auto c: cuts){ int u = edge_to_subtree[c-1]; events.push_back({ETT_in[u], false}); events.push_back({ETT_out[u], true}); } sort(all(events)); int cur = 1; stack<Node> stk; stk.push(Node()); for(auto [idx, is_end]: events){ if(is_end){ Node& top = stk.top(); top = seg.pull(top, seg.query(cur, idx)); cur = idx+1; Query_nodes.push_back(top); stk.pop(); } else{ Node& top = stk.top(); top = seg.pull(top, seg.query(cur, idx-1)); cur = idx; stk.push(Node()); } } Node& top = stk.top(); top = seg.pull(top, seg.query(cur, N)); Query_nodes.push_back(top); sort(all(Query_nodes), [](Node a, Node b){ return a.dist > b.dist; }); int ans = 0; if(Query_nodes.size() > 0) ans = Query_nodes[0].dist; if(Query_nodes.size() > 1) ans = max(ans, (Query_nodes[0].dist+1)/2 + (Query_nodes[1].dist+1)/2 + 1); if(Query_nodes.size() > 2) ans = max(ans, (Query_nodes[1].dist+1)/2 + (Query_nodes[2].dist+1)/2 + 2); cout << ans << "\n"; } } ๐Ÿ”’ ๊ตฌํ˜„ ์ฝ”๋“œ ์ž ๊ธˆ

BOJ 1734 ๊ตํ†ต ์ฒด๊ณ„

·405 words·2 mins
๐Ÿ“ ๋ฌธ์ œ ์ •๋ณด # ๋งํฌ: https://www.acmicpc.net/problem/1734 ๐Ÿง ๊ด€์ฐฐ ๋ฐ ์ ‘๊ทผ # ๋ฌดํ–ฅ ๊ทธ๋ž˜ํ”„ $G = (V, E)$๊ฐ€ ์ฃผ์–ด์ง„๋‹ค. ์—ฌ๊ธฐ์„œ ๋‘๊ฐ€์ง€ ์ฟผ๋ฆฌ๊ฐ€ ์ฃผ์–ด์ง„๋‹ค. ๊ฐ„์„  $e \in E$ ํ•˜๋‚˜๋ฅผ ์—†์•ด์„ ๋•Œ, ์ •์  $A, B$์˜ ์—ฐ๊ฒฐ์„ฑ ํŒ์ • ์ •์  $v \in V$ ํ•˜๋‚˜๋ฅผ ์—†์•ด์„ ๋•Œ, ์ •์  $A, B$์˜ ์—ฐ๊ฒฐ์„ฑ ํŒ์ • ๊ฐ๊ฐ ์‚ดํŽด๋ณด์ž. ๋จผ์ €, ๋ฌธ์ œ์กฐ๊ฑด์— ์˜ํ•ด ์ปดํฌ๋„ŒํŠธ๋Š” ํ•˜๋‚˜์ด๋ฏ€๋กœ A, B๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ์—ฐ๊ฒฐ๋˜์–ด์žˆ๋‹ค๊ณ  ํŒ๋‹จํ•˜์ž.

BOJ 3176 ๋„๋กœ ๋„คํŠธ์›Œํฌ

·146 words·1 min
๐Ÿ“ ๋ฌธ์ œ ์ •๋ณด # ๋งํฌ: https://www.acmicpc.net/problem/3176 ๐Ÿง ๊ด€์ฐฐ ๋ฐ ์ ‘๊ทผ # ๋„๋กœ๊ฐ€ N-1๊ฐœ์ธ๊ฑธ ๋ณด๋‹ˆ ํŠธ๋ฆฌ๊ฒ ๊ตฌ๋งŒ ์ด๋•Œ ๊ฒฝ๋กœ์ƒ์—์„œ ๊ฐ€์žฅ ์งง์€ ๋„๋กœ์˜ ๊ธธ์ด์™€ ๊ฐ€์žฅ ๊ธด ๋„๋กœ์˜ ๊ธธ์ด๋ฅผ ์ถœ๋ ฅํ•˜๋ผ๋Š”๋ฐ… HLD๋ฅผ ์จ๋„ ๋˜์ง€๋งŒ, sparse table์—์„œ์˜ RMQ์ฒ˜๋ฆฌ์ฒ˜๋Ÿผ ์ง„ํ–‰ํ•ด๋„ ํฐ ๋ฌธ์ œ๊ฐ€ ์—†๊ฒ ๋‹ค. ๐Ÿ’ป ํ’€์ด # ์ฝ”๋“œ (C++): void solve(){ cin >> N; rep(i, 0, N-1){ int u, v, w; cin >> u >> v >> w; links[u].push_back({v, w}); links[v].push_back({u, w}); } dfs(1, -1, 0); rep(j, 1, 20) rep(i, 1, N+1) if(par[i][j-1]){ par[i][j] = par[par[i][j-1]][j-1]; mnDist[i][j] = min(mnDist[i][j-1], mnDist[par[i][j-1]][j-1]); mxDist[i][j] = max(mxDist[i][j-1], mxDist[par[i][j-1]][j-1]); } int Q; cin >> Q; while(Q--){ int u, v; cin >> u >> v; auto [mn, mx] = calc(u, v); cout << mn << ' ' << mx << '\n'; } } ๐Ÿ”’ ๊ตฌํ˜„ ์ฝ”๋“œ ์ž ๊ธˆ

BOJ 1761 ์ •์ ๋“ค์˜ ๊ฑฐ๋ฆฌ

·226 words·2 mins
๐Ÿ“ ๋ฌธ์ œ ์ •๋ณด # ๋งํฌ: https://www.acmicpc.net/problem/1761 ๐Ÿง ๊ด€์ฐฐ ๋ฐ ์ ‘๊ทผ # ํŠธ๋ฆฌ์—์„œ, ๋‘ ์ •์  ์‚ฌ์ด์˜ ๊ฒฝ๋กœ๋Š” ์œ ์ผํ•˜๋‹ค. ํ•ด๋‹น ๊ฒฝ๋กœ๋Š” ๋‘ ์ •์ ์˜ LCA๋ฅผ ์ง€๋‚œ๋‹ค. ๋‘ ์  ์‚ฌ์ด์˜ ๊ฑฐ๋ฆฌ๋Š” $d(u) + d(v) - 2*d(\text{LCA}(u, v))$๋กœ ๊ณ„์‚ฐํ•  ์ˆ˜ ์žˆ๋‹ค. ๐Ÿ’ป ํ’€์ด # ์ฝ”๋“œ (C++): void dfs(int cur, int _par){ for(auto [nxt, w]: links[cur]){ if(nxt == _par) continue; dist[nxt] = dist[cur] + w; depth[nxt] = depth[cur] + 1; par[nxt][0] = cur; dfs(nxt, cur); } } int LCA(int u, int v){ if(u == v) return u; if(depth[u] < depth[v]) swap(u, v); int diff = depth[u] - depth[v]; rep(i, 0, 16) if((diff >> i) & 1) u = par[u][i]; if(u == v) return u; rrep(i, 16, 0){ if(par[u][i] != par[v][i]){ u = par[u][i]; v = par[v][i]; } } return par[u][0]; } ll getDist(int u, int v){ int lca = LCA(u, v); return dist[u] + dist[v] - 2 * dist[lca]; } void solve(){ cin >> N; rep(i, 0, N-1){ int u, v, w; cin >> u >> v >> w; links[u].push_back({v, w}); links[v].push_back({u, w}); } dfs(1, -1); rep(j, 1, 16) rep(i, 1, N+1) par[i][j] = par[par[i][j-1]][j-1]; cin >> Q; while(Q--){ int u, v; cin >> u >> v; cout << getDist(u, v) << '\n'; } } ๐Ÿ”’ ๊ตฌํ˜„ ์ฝ”๋“œ ์ž ๊ธˆ