zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    docker基础:docker网络模式
    WEB架构师成长之路之一-走正确的路(转载)
    DDD(领域驱动设计)
    C#泛型和泛型约束(转载)
    MES系统介绍
    vue中 computed和watch的一些简单理解(区别)(转载)
    sqlserver常用表值函数
    SQLServerAgent 当前未运行,因此无法将此操作通知它。
    浅谈敏捷开发(转载)
    认证、授权、鉴权和权限控制(转载)
  • 原文地址:https://www.cnblogs.com/cjoieryl/p/10383517.html
Copyright © 2011-2022 走看看