Manthan, Codefest 18 (rated, Div. 1 + Div. 2) D. Valid BFS?

题意:给一个树和一个bfs序,并保证从节点1出发,判bfs序是否合法。

思路:双指针,在bfs序上从左往右遍历。慢指针指向当前节点u,快指针指向当前节点应该访问的节点的位置。 然后设两个集合,一个集合存储在当前节点上应该访问的节点,另一个存储在当前节点上实际访问的节点,然后遍历即可。

总结:一开始想的是对每个节点求一个深度,然后保证节点的深度非递减排序就行了,但是这个算法有个bug,就是如果同层节点的访问顺序不同,那么下一层的节点访问顺序也不同,即使它们的深度都是一样的,这种深度判定的方法漏掉了这种情况。

void solve(){
    int n;
    cin >> n;

    vector<vector<int>> al(n);
    for (int i = 0; i < n - 1; ++i){
        int u, v;
        cin >> u >> v;
        u --;
        v --;
        al[u].emplace_back(v);
        al[v].emplace_back(u);
    }

    vector<int> order(n);
    for (int i = 0; i < n; ++i){
        int cur;
        cin >> cur;
        cur --;
        order[i] = cur;
    }

    vector<bool> vis(n);
    vis[0] = 1;
    bool ok = true;
    int i, j;
    for (i = 0, j = 1; i < n; ){
        int u = order[i];
        set<int> should_vis;
        for (const int& v : al[u]){
            if (vis[v] == false){
                should_vis.insert(v);
            }
        }
        set<int> has_vis;
        for (int s = j; s < j + int(should_vis.size()); ++s){
            has_vis.insert(order[s]);
        }
        if (has_vis != should_vis){
            ok = false;
            break;
        }
        for (const int& v : should_vis){
            vis[v] = true;
        }
        i ++;
        j += int(should_vis.size());
    }

    cout << (ok ? "Yes" : "No") << '\n';
}
posted @ 2024-04-29 10:02  _Yxc  阅读(6)  评论(0编辑  收藏  举报