zzuli 2525: 咕咕的搜索序列

题目链接

题意

给一个长度为 M M 的序列,问它是否能作为给定的一棵树的dfs序的一部分

思路

比赛的时候和队友在写假算法,本来以为会 T L E TLE 或者 M L E MLE ,但是一直 W A WA
回来问了学长才过的。
按照给定序列的顺序从下到上打上同一个标记,遇到打过标记的点就 r e t u r n return ,然后按照标记从小到大 d f s dfs 得到一个 d f s dfs 序,最后查找序列是否出现在 d f s dfs 序列里面。
因为 d f s dfs 结束之后才加入队列,所以序列前面的节点最先访问,这是就给他打上一个小的标记,这样只要序列正确,一定会出现在 d f s 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;
}

猜你喜欢

转载自blog.csdn.net/henuyh/article/details/89320233
今日推荐