hrbustOJ 1373Leyni, LOLI and Leaders(图论)
摘自:http://acm.hrbust.edu.cn/hcpc2012/index.php?act=showpost&p=15
本题是图论题
根据题意,判断一颗树中,某个点是否是另一个点的后裔。根据递归函数的入栈出栈时间戳特点(即子结点的入栈时间戳要晚于自己,而且子节点的出栈时间戳要早于自己)或者括号定理在O(N)内预处理一遍图,即可在O(1)时间完成每次查询。
d[x]表示深度优先搜索中x的访问时间戳
f[x]表示深度优先搜索中x的结束访问时间戳
如果d[u] < d[v] < f[v] < f[u],那么v是u的后裔。
1 #include <cstdio> 2 #include <cstdlib> 3 #include <iostream> 4 5 using namespace std; 6 7 const int N = 100005; 8 9 bool color[N]; 10 int d[N], f[N], times; 11 struct edge { 12 int v; 13 edge *next; 14 edge(int vv, edge *p) { 15 v = vv; 16 next = p; 17 } 18 }; 19 20 struct graph { 21 edge *link; 22 }G[N]; 23 24 void initG(int n) { 25 for (int i=1; i<=n; ++i) G[i].link = NULL; 26 } 27 28 void buildG(int u, int v) { 29 edge *p = new edge(v, G[u].link); 30 G[u].link = p; 31 } 32 33 void dfsVisit(int u) { 34 color[u] = true; 35 d[u] = times = times + 1; 36 for (edge *p=G[u].link; p; p=p->next) { 37 if (!color[p->v]) dfsVisit(p->v); 38 } 39 f[u] = times = times + 1; 40 } 41 42 void dfs(int n, int s) { 43 for (int i=1; i<=n; ++i) color[i] = false; 44 times = 0; 45 for (edge *p=G[s].link; p; p=p->next) { 46 if (!color[p->v]) dfsVisit(p->v); 47 } 48 } 49 50 void del(edge *p) { 51 if (!p) return ; 52 del(p->next); 53 delete p; 54 } 55 56 int main() { 57 int t; 58 scanf ("%d", &t); 59 while (t--) { 60 int q, n, u, v, s; 61 scanf ("%d", &n); 62 initG(n); 63 for (int i=1; i<=n; ++i) { 64 scanf ("%d", &u); 65 if (u) buildG(u, i); 66 else s = i; 67 } 68 buildG(s, s); 69 dfs(n, s); 70 scanf ("%d", &q); 71 while (q--) { 72 scanf ("%d%d", &u, &v); 73 if (d[u] < d[v] && f[v] < f[u]) printf ("%d>%d\n", u, v); 74 else if (d[v] < d[u] && f[u] < f[v]) printf ("%d<%d\n", u, v); 75 else printf ("%d<>%d\n", u, v); 76 } 77 for (int i=1; i<=n; ++i) del(G[i].link); 78 } 79 return 0; 80 }