题意
给一个长度为 的序列,问它是否能作为给定的一棵树的dfs序的一部分
思路
比赛的时候和队友在写假算法,本来以为会
或者
,但是一直
。
回来问了学长才过的。
按照给定序列的顺序从下到上打上同一个标记,遇到打过标记的点就
,然后按照标记从小到大
得到一个
序,最后查找序列是否出现在
序列里面。
因为
结束之后才加入队列,所以序列前面的节点最先访问,这是就给他打上一个小的标记,这样只要序列正确,一定会出现在
序中
#include <bits/stdc++.h>
#define LL long long
#define P pair<int, int>
#define lowbit(x) (x & -x)
#define mem(a, b) memset(a, b, sizeof(a))
#define mid ((l + r) >> 1)
#define lc rt<<1
#define rc rt<<1|1
using namespace std;
const int maxn = 1e6 + 1;
vector<int> g[maxn], num;
int fa[maxn], sign[maxn], now;
void dfs(int x) {
for (int it : g[x]) {
dfs(it);
}
num.push_back(x);
}
bool cmp(int x, int y) {
return sign[x] < sign[y];
}
int main () {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int T;
scanf("%d", &T);
while (T--) {
int n, m;
scanf("%d%d", &n, &m);
vector<int> list(m);
now = 0;
for (int i = 1; i <= n; ++i) sign[i] = 0, g[i].clear();
for (int i = 2, x; i <= n; ++i) {
scanf("%d", &x);
g[x].push_back(i);
fa[i] = x;
}
for (int i = 0; i < m; ++i) {
scanf("%d", &list[i]);
now = i+1;
int tmp = list[i];
while (sign[tmp] == 0) {
sign[tmp] = now;
tmp = fa[tmp];
if (tmp == 0) break;
}
}
for (int i = 1; i <= n; ++i) {
sort(g[i].begin(), g[i].end(), cmp);
}
num.clear();
dfs(1);
int flag = 1;
int j = 0;
for (int i = 0; i < n; ++i) {
if (num[i] == list[j]) j++;
if (j == m) break;
}
if (j != m) flag = 0;
puts(flag ? "NOT BAD":"BAD GUGU");
}
return 0;
}