Codeforces 750 F:New Year and Finding Roots

Posted cjoieryl

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces 750 F:New Year and Finding Roots相关的知识,希望对你有一定的参考价值。

传送门
首先如果一开始就找到了一个叶子,那么暴力去递归找它的父亲,每次随机一个方向(除了已知的儿子)走深度次,如果走到了一个叶子就不是这个方向
(设根的深度为 (1))这样子最后到达深度为 (3) 的点需要花费 (11)
注意到此时只有与该点距离不超过 (2) 的点可能是根,这样的没有询问过的点不超过 (6)
所以只要询问 (5) 次,一共 (16)
如果一开始不是叶子,那么尝试 (dfs) 到一个叶子,最后再套用上面的做法
注意每次随机一个方向的时候要判断之前是否已经有一条长度为深度的链(也可以优先选择询问过的点)

# include <bits/stdc++.h>
using namespace std;
typedef long long ll;

int h, pre[233], vis[233], n, flg, rt, leaf, actur[233], tot;
vector <int> son[233];

inline void Ask(int u) {
    if (vis[u]) return;
    int cnt, i, v;
    vis[u] = 1, printf("? %d
", u), fflush(stdout);
    scanf("%d", &cnt);
    for (i = 0; i < cnt; ++i) scanf("%d", &v), son[u].push_back(v);
    if (son[u].size() == 2) {
        rt = u, flg = 1;
        return;
    }
}

void Dfs(int cur) {
    if (leaf || flg) return;
    int i, cnt;
    Ask(cur), cnt = son[cur].size();
    if (cnt == 1) {
        leaf = cur;
        return;
    }
    if (leaf || flg) return;
    for (i = 0; i < cnt; ++i)
        if (!vis[son[cur][i]]) {
            pre[son[cur][i]] = cur, Dfs(son[cur][i]);
            return;
        }
}

inline int Check(int u, int ff, int d) {
    if (d < 0) return 0;
    Ask(u);
    if (flg) return 1;
    if (son[u].size() == 1) return d ? 0 : actur[u] = 1;
    int i;
    for (i = 0; i < 3; ++i)
        if ((son[u][i] ^ ff) && vis[son[u][i]]) {
            if (Check(son[u][i], u, d - 1)) return actur[u] = 1;
            return 0;
        }
    for (i = 0; i < 3; ++i)
        if ((son[u][i] ^ ff) && !vis[son[u][i]]) {
            if (Check(son[u][i], u, d - 1)) return actur[u] = 1;
            return 0;
        }
}

inline int Getfa(int x, int nh) {
    Ask(x);
    if (son[x].size() == 1) return son[x][0];
    if (flg) return 0;
    int p1, p2, i;
    for (i = 0; i < 3; ++i) if (actur[son[x][i]]) break;
    if (i == 0) p1 = 1, p2 = 2;
    else if (i == 1) p1 = 0, p2 = 2;
    else p1 = 0, p2 = 1;
    p1 = son[x][p1], p2 = son[x][p2];
    if (vis[p2]) swap(p1, p2);
    return Check(p1, x, h - nh - 1) ? p2 : p1;
}

void Dfs2(int u, int d) {
    if (d > 2 || flg) return;
    if (tot == 6) {
        rt = u, flg = 1;
        return;
    }
    Ask(u), ++tot;
    if (flg) return;
    int i, cnt = son[u].size();
    for (i = 0; i < cnt; ++i)
        if (!actur[son[u][i]]) Dfs2(son[u][i], d + 1);
}

inline void Solve() {
    int cur, i, nh;
    memset(pre, 0, sizeof(pre));
    memset(vis, 0, sizeof(vis));
    memset(actur, 0, sizeof(actur));
    scanf("%d", &h), n = (1 << h) - 1, leaf = flg = 0, nh = h;
    for (i = 1; i <= n; ++i) son[i].clear();
    cur = rand() % n + 1, Dfs(cur);
    if (flg) {
        printf("! %d
", rt), fflush(stdout);
        return;
    }
    cur = leaf, actur[cur] = 1;
    while (nh > 3) {
        cur = Getfa(cur, nh), --nh, actur[cur] = 1;
        if (flg) {
            printf("! %d
", rt), fflush(stdout);
            return;
        }
    }
    tot = 0, Dfs2(cur, 0);
    printf("! %d
", rt), fflush(stdout);
}

int main() {
    srand(time(NULL));
    int test;
    scanf("%d", &test);
    while (test--) Solve();
    return 0;
}

以上是关于Codeforces 750 F:New Year and Finding Roots的主要内容,如果未能解决你的问题,请参考以下文章

Codeforces 750 E New Year and Old Subsequence

New Year and Old Subsequence CodeForces - 750E(线段树 + 矩阵)

CodeForces - 750D New Year and Fireworks

codeforces 750D New Year and FireworksDFS

Codeforces 750E New Year and Old Subsequence - 线段树 - 动态规划

Codeforces 750E New Year and Old Subsequence 线段树 + dp (看题解)