โจทย์: กำหนด rooted tree และ Q queries แต่ละ query ให้ 2 โหนด ตรวจสอบว่าโหนดหนึ่งเป็น ancestor ของอีกตัวหรือไม่
เทคนิค: DFS Timestamps (Euler Tour)
- DFS จาก root บันทึก
timeIn[u](เวลาเข้า) และtimeOut[u](เวลาออก) - u เป็น ancestor ของ v ↔
timeIn[u] ≤ timeIn[v] AND timeOut[v] ≤ timeOut[u] - ตอบ query O(1) หลัง preprocessing O(N)
ตัวอย่างโค้ด C++
#include <bits/stdc++.h>
using namespace std;
void performingDFS(vector<int> g[], int u, int parent, int timeIn[], int timeOut[], int& count) {
timeIn[u] = count++;
for (int v : g[u]) {
if (v != parent)
performingDFS(g, v, u, timeIn, timeOut, count);
}
timeOut[u] = count++;
}
void processingEdges(int edges[][2], int V, int timeIn[], int timeOut[]) {
vector<int> g[V];
for (int i = 0; i < V-1; i++) {
int u = edges[i][0], v = edges[i][1];
g[u].push_back(v);
g[v].push_back(u);
}
int count = 0;
performingDFS(g, 0, -1, timeIn, timeOut, count);
}
string whetherAncestor(int u, int v, int timeIn[], int timeOut[]) {
bool b = (timeIn[u] <= timeIn[v] && timeOut[v] <= timeOut[u]);
return b ? "yes" : "no";
}
int main() {
int edges[][2] = {{0,1},{0,2},{1,3},{1,4},{2,5}};
int E = sizeof(edges)/sizeof(edges[0]);
int V = E + 1;
int timeIn[V], timeOut[V];
processingEdges(edges, V, timeIn, timeOut);
cout << whetherAncestor(1, 5, timeIn, timeOut) << endl; // no
}
อินพุต
edges: (0,1),(0,2),(1,3),(1,4),(2,5), query: u=1, v=5
เอาต์พุท
no
Complexity
- Preprocessing: O(N)
- Per query: O(1)
- Space: O(N)