题意概述
这是一个交互题。
有一棵有 \(n\) 个节点的树,节点编号从 \(1\) 到 \(n\) ,并要求你使用以下类型的查询来猜测它:
"? a b"
会告诉你哪个节点 \(x\) 在点 \(a\) 和 \(b\) 之间(\(|d(a,x) - d(b,x)|\) 的值最小),其中 \(d(x,y)\) 是节点 \(x\) 和 \(y\) 之间的距离。如果存在不止一个这样的节点,那么会告诉你哪个节点在哪一个 \(x\) 使 \(d(a,x)\) 最小。
用最多 \(15n\) 次查询找出树的结构。
思路
对于每一个 \(n\) 我们可以深搜节点编号 \(p\) 的点和 \(i\) 之间的节点,得到的值为 \(w\) 若 \(w\) 和 \(p\) 相等就在 \(p\) 和 \(i\) 之间连一条边,否则就继续深搜 \(w\) 和 \(i\),初始时 \(p\) 等于 \(1\),\(2 \le i \le n\)。对于每次输出使用 fflush(stdout);
清空缓存。输出格式! a1 b1 a2 b2……
。
代码
#include <bits/stdc++.h>
#define ll long long
#define N 100001
#define mod 998244353
#define ios std::ios::sync_with_stdio(false)
#define itie std::cin.tie(0)
#define otie std::cout.tie(0)
std::mt19937_64 mrand(std::random_device{}());
int Test;
std::vector<int> a, b;
inline void solve(int p, int i) {
std::cout << "? " << p << " " << i << std::endl;
fflush(stdout);
int w;
std::cin >> w;
if (w == p) {
a.push_back(p),
b.push_back(i);
return;
}
solve(w, i);
}
int main() {
std::cin >> Test;
for ( ; Test--; ) {
int n;
std::cin >> n;
a.clear();
b.clear();
for (int i = n; i >= 2; i--)
solve(1, i);
std::cout << "! ";
for (int i = 0; i < n - 1; i++)
std::cout << a[i] << " " << b[i] << " ";
puts("");
fflush(stdout);
}
}
标签:std,967,cout,int,Codeforces,Test,Div,节点,define
From: https://www.cnblogs.com/Sliver-jiblogs/p/18377713