B. Beggin' For A Node

time limit per test2.0 s

memory limit per test256 MB

inputstandard input

outputstandard output

This is an interactive problem

Low_ has a beautiful tree, which he keeps very carefully. A tree is a tree, but mathematically, it could be modeled as an indirect connected graph with no cycles. Suppose low_'s tree has n nodes and n−1 edges.

S_e_o is low_'s friend, and he has been attracted to the Codeforces golden secret for a long time. He does not want to hurt his friend by taking it illegally, especially from his beloved tree, so S_e_o comes up with a devious plan. He hides the golden secret in a node of low_'s favorite tree and challenges him to find that node by interacting with an A.I bot which was created by another hacker named b21. There are two types of question that low_ could beg for:

"?1u": The bot will return number of edges on the simple path from node u to the hidden node.

"?2u": The bot will return the second node on the simple path from node u to the hidden node. If this type of query is asked for the hidden node by luck, the bot will return 0.

Low_ does not want his friend to read his own secret to become master at Codeforces, so he has to be quick. Please help him, and remember to be quick by only asking no more than 36 queries.

Input

The first line contains an integer n (1≤n≤200000).

The next n−1 lines, each contains two integers u and v (1≤u,v≤n) denotes that there's an edge connects u and v in the tree.

Interaction

You can make queries of type "? T u" to the robot. T is either 1 or 2, and 1≤u≤n. The description for query is stated in the problem legend.

After the query read its result as an integer. If you read −1, that means your query is in the wrong format, or you have exceeded 36 queries. Exit the program immediately to get the verdict "Wrong answer". If you don't, you might get an arbitrary verdicts.

When you find out the array, print "!" followed by a space and an integer denotes your answer. This is not counted as a query, but you only have one guess. If you failed to get the answer right, your verdict will be "Wrong answer".

After printing any query do not forget to output end of line and flush the output. Otherwise you will get Idleness limit exceeded. To do this, use:

fflush(stdout) or cout.flush() in C++;

System.out.flush() in Java;

flush(output) in Pascal;

stdout.flush() in Python.

Example

inputCopy

7

2 1

2 4

3 5

6 2

1 3

2 7

1

3

0

outputCopy

? 2 2

? 1 6

? 1 3

! 3

题意:

自行读题。

思路:

我们设隐藏的节点为X。

树的重心,也叫树的质心。对于一棵树来说,删去该树的重心后,所有的子树的大小不会超过原树大小的二分之一

我们利用这个性质,我们先找到整个树的重心Y,然后问其到X的第二个节点是哪个。假设是U,

然后断开U和Y的连接,这样剩下的包含U这一块的部分肯定是含有X节点的。并且节点个数小于等于之前的二分之一,

继续重复上面行为,直至回答0,即找到了节点X。

因为我们每一次递归节点个数都减少一半,那么我们最多20次左右即可找到X节点,因为 2^20>=2e5

这里断开连接并不是删除边,而是用了一个数组bool cut[i] 表示第i个节点是否被隔开,如果是dfs就不访问即可。

细节见代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <iomanip>
#define ALL(x) (x).begin(), (x).end()
#define sz(a) int(a.size())
#define all(a) a.begin(), a.end()
#define rep(i,x,n) for(int i=x;i<n;i++)
#define repd(i,x,n) for(int i=x;i<=n;i++)
#define pii pair<int,int>
#define pll pair<long long ,long long>
#define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define MS0(X) memset((X), 0, sizeof((X)))
#define MSC0(X) memset((X), '\0', sizeof((X)))
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define eps 1e-6
#define gg(x) getInt(&x)
#define chu(x) cout<<"["<<#x<<" "<<(x)<<"]"<<endl
using namespace std;
typedef long long ll;
ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
ll lcm(ll a, ll b) {return a / gcd(a, b) * b;}
ll powmod(ll a, ll b, ll MOD) {ll ans = 1; while (b) {if (b % 2)ans = ans * a % MOD; a = a * a % MOD; b /= 2;} return ans;}
inline void getInt(int* p);
const int maxn = 200010;
const int inf = 0x3f3f3f3f;
/*** TEMPLATE CODE * * STARTS HERE ***/
std::vector<int> son[maxn];
int n;
int cntnum;
int cntson[maxn];
bool cut[maxn];
int ask(int op, int x)
{
cout << "? " << op << " " << x << endl;
int res;
cin >> res;
return res;
}
int center(int x, int pre)// 求剩下树的部分的重心
{
for (auto y : son[x])
{
if (y != pre && !cut[y] && cntson[y] > cntnum / 2)
{
return center(y, x);
}
}
return x;
}
void predfs(int x, int pre)// 处理出剩下树中以x为根的子树节点个数
{
cntson[x] = 1;
for (auto y : son[x])
{
if (y != pre && !cut[y])
{
predfs(y, x);
cntson[x] += cntson[y];
}
}
}
void solve(int x)
{
predfs(x, x);
cntnum = cntson[x];// 当前剩余的节点个数
int NEXT;
x = center(x, x);
NEXT = ask(2, x);
if (!NEXT)
{
cout << "! " << x << endl;
} else
{
cut[x] = 1;// 相当于隔断next 与 x连接的边。
solve(NEXT);
}
}
int main()
{
scanf("%d", &n);
repd(i, 2, n)
{
int u, v;
scanf("%d %d", &u, &v);
son[u].push_back(v);
son[v].push_back(u);
}
solve(1); return 0;
} inline void getInt(int* p) {
char ch;
do {
ch = getchar();
} while (ch == ' ' || ch == '\n');
if (ch == '-') {
*p = -(getchar() - '0');
while ((ch = getchar()) >= '0' && ch <= '9') {
*p = *p * 10 - ch + '0';
}
}
else {
*p = ch - '0';
while ((ch = getchar()) >= '0' && ch <= '9') {
*p = *p * 10 + ch - '0';
}
}
}

HCW 19 Team Round (ICPC format) B. Beggin' For A Node(树的重心,交互题)的更多相关文章

  1. HCW 19 Team Round (ICPC format) H Houston, Are You There?(极角排序)

    题目链接:http://codeforces.com/gym/102279/problem/H 大致题意: 你在一个定点,你有个长度为R的钩子,有n个东西在其他点处,问你能勾到的东西的数量是多少? 思 ...

  2. Codeforces Round #359 (Div. 2) D. Kay and Snowflake 树的重心

    题目链接: 题目 D. Kay and Snowflake time limit per test 3 seconds memory limit per test 256 megabytes inpu ...

  3. AIM Tech Round 4 (Div. 1) C - Upgrading Tree 构造 + 树的重心

    C - Upgrading Tree 我发现我构造题好弱啊啊啊. 很明显能想到先找到重心, 然后我们的目标就是把所有点接到重心的儿子上,让重心的儿子子树变成菊花图, 这个先把重心到儿子的边连到 i , ...

  4. Codeforces Round #427 (Div. 2) E. The penguin's game (交互题,二进制分组)

    E. The penguin's game time limit per test: 1 second memory limit per test: 256 megabytes input: stan ...

  5. 2017ACM暑期多校联合训练 - Team 4 1004 HDU 6070 Dirt Ratio (线段树)

    题目链接 Problem Description In ACM/ICPC contest, the ''Dirt Ratio'' of a team is calculated in the foll ...

  6. Codeforces Round #222 (Div. 1) D. Developing Game 线段树有效区间合并

    D. Developing Game   Pavel is going to make a game of his dream. However, he knows that he can't mak ...

  7. Bestcoder round #65 && hdu 5592 ZYB's Premutation 线段树

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submissio ...

  8. Educational Codeforces Round 6 E. New Year Tree dfs+线段树

    题目链接:http://codeforces.com/contest/620/problem/E E. New Year Tree time limit per test 3 seconds memo ...

  9. 2017 Multi-University Training Contest - Team 9 1002&&HDU 6162 Ch’s gift【树链部分+线段树】

    Ch’s gift Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total S ...

随机推荐

  1. Redis ==> 集群的三种模式

    一.主从同步/复制 通过持久化功能,Redis保证了即使在服务器重启的情况下也不会丢失(或少量丢失)数据,因为持久化会把内存中数据保存到硬盘上,重启会从硬盘上加载数据. 但是由于数据是存储在一台服务器 ...

  2. 深入理解python中函数传递参数是值传递还是引用传递

    深入理解python中函数传递参数是值传递还是引用传递 目前网络上大部分博客的结论都是这样的: Python不允许程序员选择采用传值还是传 引用.Python参数传递采用的肯定是"传对象引用 ...

  3. 【AMAD】dramatiq -- Python3实现的一个快速的,可信赖的分布式任务处理库

    简介 动机 作用 用法 热度分析 个人评分 简介 Python3实现的一个快速的,可信赖的分布式任务处理库. 动机 dramatq1的官网2写道: Dramatiq成为现实的主要原因是,我想要一个简单 ...

  4. 【Qt开发】【计算机视觉】OpenCV在Qt-MinGw下的编译库

    最近电脑重装系统了,第一件事重装OpenCV.这次直接装最新版,2014-4-25日发布的OpenCV2.4.9版本,下载链接: http://sourceforge.NET/projects/ope ...

  5. 【DSP开发】【VS开发】PCIE设备扫描过程

    初步了解完PCI总线标准之后,我们接下来正式开始PCIe设备的漫游之旅.从我们按下PC的电源按钮开始,BIOS就接管系统控制权开始工作,它会先进行一些内存和设备的初始化工作(当然,也包括我们的PCI设 ...

  6. C++学习笔记-面向对象模型探究

    C++中的class从面向对象理论出发,将变量(属性)和函数(方法)集中定义在一起,用于描述现实世界中的类.从计算机的角度,程序依然由数据段和代码段构成.那么C++编译器如何完成面向对象理论到计算机程 ...

  7. Android Studio出现:Cause: unable to find valid certification path to requested target

    我的AS版本是3.4.1..出现这个问题是因为公司内网很奇葩,连上后必须访问一次网页.所以是AS连不上网络,访问不了https://bintray.com/bintray/jcenter导致的.

  8. web端 微软 RDLC 报表插件 宽大于高 横向打印失效 解决方案

    起因于系统报表工具使用的RDLC,本地测试一直使用的纵向打印,未测试过横向打印

  9. vs2019编译opencv

    序 微软家的宇宙第一ide:visual studio已经更新到了2019版,芒果也更新尝鲜了一遍,体验还不错,建议更新尝尝鲜.芒果顺便使用vs2019编译了一遍opencv,编译过程也非常顺利,以下 ...

  10. java-阿里云发送短信

    <!--aliyun短信sdk--> <dependency> <groupId>com.aliyun</groupId> <artifactId ...