题解:P7597 「EZEC-8」猜树 加强版
比较经典的想到距离为
容易想到,假设我们在
而我们实在是不能通过询问或者什么算法知道重儿子,那么我们考虑直接在
询问次数大约是个
:::success[Ac Code]
#include <bits/stdc++.h>
using namespace std;
#ifdef __linux__
#define gc getchar_unlocked
#define pc putchar_unlocked
#else
#define gc _getchar_nolock
#define pc _putchar_nolock
#endif
#define int long long
#define _ read<int>()
#define rint register int
inline bool blank(const char &x)
{
return !(x^13)||!(x^9)||!(x^32)||!(x^10);
}
template<class T>inline T read()
{
T r=0,f=1;char c=gc();
while(!isdigit(c))
{
if(c=='-') f=-1;
c=gc();
}
while(isdigit(c)) r=(r<<1)+(r<<3)+(c^48),c=gc();
return f*r;
}
inline void out(rint x)
{
if(x<0) pc('-'),x=-x;
if(x<10) pc(x+'0');
else out(x/10),pc(x%10+'0');
}
inline void read(char &x)
{
for(x=gc();(x^-1)&&blank(x);x=gc());
}
mt19937 rnd(time(0));
const int N=5005;
int dep[N],fa[N],n;
bitset<N>vis;
inline int qry(rint u,rint v)
{
pc('?'),pc(' '),pc('1'),pc(' '),out(u),pc(' ');out(v);pc('\n');fflush(stdout);
return _;
}
inline vector<int> qry1(rint x)
{
vector<int>s;
pc('?'),pc(' '),pc('2');pc(' '),out(x);pc('\n');
fflush(stdout);
rint m=_;
for(rint i=1;i<=m;++i) s.push_back(_);
return s;
}
vector<int>s;
inline void dfs(rint u,vector<int>s)
{
if(s.empty()) return ;
vector<int>son;
for(auto x:s)
{
if(dep[x]-dep[u]==1) son.push_back(x),fa[x]=u;
}
rint h=s[rnd()%s.size()];
// cerr<<h<<endl;
shuffle(son.begin(),son.end(),rnd);
rint hea=son.back();
for(auto x:son)
{
if(x==son.back()) continue;
if(x==h)
{
hea=x;break;
}
rint d=qry(x,h);
if(dep[h]-dep[x]==d)
{
hea=x;break;
}
}
for(auto x:s) vis[x]=0;
vector<int>hs;
vector<pair<int,vector<int>>>S;
for(auto v:son)
{
if(v==hea) continue;
auto p=qry1(v);vector<int>vp;
for(auto x:p)
{
vis[x]=1;
if(x!=v) vp.push_back(x);
}
S.push_back({v,vp});vp.clear();p.clear();
}
for(auto x:s)
{
if(vis[x]||x==hea) continue;
hs.push_back(x);
}
for(auto &p:S)
{
dfs(p.first,p.second);
}
dfs(hea,hs);
}
signed main()
{
n=_;
for(rint i=2;i<=n;++i)
{
dep[i]=qry(1,i);
s.push_back(i);
}
dfs(1,s);
pc('!');
for(rint i=2;i<=n;++i) pc(' '),out(fa[i]);pc('\n');fflush(stdout);
return 0;
}
:::