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';
}
}
}

最新文章

  1. linux用户权限相关内容查看
  2. IPv6实验准备
  3. SQLServer性能调优3之索引(Index)的维护
  4. __cdecl __stdcall __fastcall之函数调用约定讲解
  5. python脚本实例001 - 通过列表内容判断输入输出信息
  6. pgsql自动安装shell脚本整理
  7. &lt;转载&gt;Win32控制台工程中创建窗口
  8. 浅谈JavaScript中的内存管理
  9. openStack error infos 调试
  10. 笔试题&amp;amp;面试题:输入一个维度,逆时针打印出一个指定矩阵
  11. Leetcode: UniquePath II
  12. 使用jmeter+ant进行接口自动化测试(数据驱动)之二:利用apache-ant执行测试用例并生成HTML格式测试报告
  13. POJ-1251 Jungle Roads---MST裸题(需要编号)
  14. (转)JPA &amp; Restful
  15. jquery中ajax处理跨域的三大方式
  16. Tomcat7.0安装配置详细(图文)
  17. CSS 小结笔记之伸缩布局 (flex)
  18. VS2010整合NUnit进行单元测试
  19. C语言学习笔记 (002) - C++中引用和指针的区别(转载)
  20. JFinal ORM和Hibernate简要对比

热门文章

  1. SQL Server 收集数据库死锁信息
  2. ELK 日志平台构建
  3. GPU编程shader之正余弦波和幂/指数函数
  4. EncryptFac 加解密小工具
  5. AESTest
  6. HNU_团队项目_需求分析感想(全员)
  7. 【ABAP系列】SAP 使用特殊的技术更新数据库(ABAP)
  8. window启动目录
  9. PTA(Basic Level)1032.挖掘机技术哪家强
  10. Longest Palindromic Subsequence