题解 P9462
Solution
考虑
我们规定
对于任意树的情况,我们先尝试找到两个相邻的点:
先询问每个点和
然后考虑使用 bfs 优化上述迭代过程:我们在临时父亲
操作次数为较难卡满的
Code
#include<bits/stdc++.h>
using namespace std;
inline int read(){
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;
}
int query(int x,int y)
{
printf("? %d %d\n",x,y),
fflush(stdout);
return read();
}
int a[10003],b[10003],fa[10003];
vector<int> v[10003],d[10003];
void dfs(int x)
{
for(int y:v[x])
dfs(y),b[x]=max(b[x],b[y]+1);
return ;
}
signed main()
{
int n=read(),id=2;
a[1]=1;
for(int i=2; i<=n; ++i)
{
a[i]=query(1,i);
if(a[i]) v[a[i]].push_back(i),a[i]=1;
}
for(int i=2; i<=n; ++i)
{
if(!a[i]) dfs(i);
if(b[i]>b[id]) id=i;
}
queue<int> q;
fa[1]=id,fa[id]=1,q.push(1),q.push(id);
for(int i=2; i<=n; ++i) if(i!=id) d[1].push_back(i);
while(!q.empty())
{
int x=q.front();
q.pop();
for(int y:d[x])
{
if(a[x]^a[y])
{
int z=query(fa[x],y);
if(z==x) fa[y]=x,q.push(y);
else d[z].push_back(y);
}
else d[query(x,y)].push_back(y);
}
vector<int>().swap(d[x]);
}
puts("!");
for(int i=2; i<=n; ++i) printf("%d %d\n",fa[i],i);
return 0;
}