您的位置:首页 > 其它

hrbustOJ 1373Leyni, LOLI and Leaders(图论)

2012-04-27 17:18 323 查看
摘自: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的后裔。

#include <cstdio>
#include <cstdlib>
#include <iostream>

using namespace std;

const int N = 100005;

bool color
;
int d
, f
, times;
struct edge {
int v;
edge *next;
edge(int vv, edge *p) {
v = vv;
next = p;
}
};

struct graph {
edge *link;
}G
;

void initG(int n) {
for (int i=1; i<=n; ++i) G[i].link = NULL;
}

void buildG(int u, int v) {
edge *p = new edge(v, G[u].link);
G[u].link = p;
}

void dfsVisit(int u) {
color[u] = true;
d[u] = times = times + 1;
for (edge *p=G[u].link; p; p=p->next) {
if (!color[p->v]) dfsVisit(p->v);
}
f[u] = times = times + 1;
}

void dfs(int n, int s) {
for (int i=1; i<=n; ++i) color[i] = false;
times = 0;
for (edge *p=G[s].link; p; p=p->next) {
if (!color[p->v]) dfsVisit(p->v);
}
}

void del(edge *p) {
if (!p) return ;
del(p->next);
delete p;
}

int main() {
int t;
scanf ("%d", &t);
while (t--) {
int q, n, u, v, s;
scanf ("%d", &n);
initG(n);
for (int i=1; i<=n; ++i) {
scanf ("%d", &u);
if (u) buildG(u, i);
else s = i;
}
buildG(s, s);
dfs(n, s);
scanf ("%d", &q);
while (q--) {
scanf ("%d%d", &u, &v);
if (d[u] < d[v] && f[v] < f[u]) printf ("%d>%d\n", u, v);
else if (d[v] < d[u] && f[u] < f[v]) printf ("%d<%d\n", u, v);
else printf ("%d<>%d\n", u, v);
}
for (int i=1; i<=n; ++i) del(G[i].link);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: