题意:给你一个树结构,每次可以询问两个结点的LCA,问你树的根。
每次找出两个度为1的结点查询,
(1)如果LCA等于某点,则由于两点度数为1,不是叶子结点就是根节点,由于一个叶子结点不可能为另一个叶子的祖先,则一个点为根结点,一个点为叶子
(2)否则这两个结点一定为两个叶子结点,将他们直接删除
还有就是删除的时候set的应用
//从叶子结点开始删除,直到最后剩下根结点 or 求出当前某一结点为叶子结点
set<int>mp[1111];
int ans[1111];
void solve()
{
int n;cin>>n;
rpp(i,n-1)
{
int u,v;cin>>u>>v;
mp[u].insert(v);
mp[v].insert(u);
}
while(1)
{
ans[0]=0;
rpp(i,n)
if(mp[i].size()==1) ans[++ans[0]]=i;
cout<<"? "<<ans[1]<<" "<<ans[2]<<endl;
fflush(stdout);
int x;cin>>x;
if(x==ans[1]||x==ans[2])
{
cout<<"! "<<x<<endl;
return ;
}
//将该叶子结点删除
//即将他在与他相连的父节点图中删除该点
//然后将该点连接的边清空
mp[*mp[ans[1]].begin()].erase(ans[1]);
mp[ans[1]].clear();
mp[*mp[ans[2]].begin()].erase(ans[2]);
mp[ans[2]].clear();
if(mp[x].empty())
{
cout<<"! "<<x<<endl;
return ;
}
}
}
signed main()
{
int T = 1;
while (T--)
solve();
return 0;
}