總結
人生第一次寫的一個交互題,迷迷糊糊的將就AC了,也算敷衍的補了一個題吧!
解析
如果每次刪除非根的葉子結點,最多n/2次就能找到root
最壞極端情況:滿二叉樹,每次刪除底層的最右邊兩個葉子結點
最快極端情況:線性樹,一次得到root,且後面不再改變。
#include<bits/stdc++.h>
//typedef long long ll;
//#define ull unsigned long long
//#define int long long
#define F first
#define S second
#define endl "\n"
#define eps 1e-6
#define lowbit(x) (x&(-x))
#define PI acos(-1.0)
#define inf 0x3f3f3f3f
#define MAXN 0x7fffffff
#define INF 0x3f3f3f3f3f3f3f3f
#define ferma(a,b) pow(a,b-2)
#define pb push_back
#define all(x) x.begin(),x.end()
#define memset(a,b) memset(a,b,sizeof(a));
#define IOS ios::sync_with_stdio(false);//cin.tie(0),cout.tie(0);
using namespace std;
void file()
{
#ifdef ONLINE_JUDGE
#else
freopen("cin.txt","r",stdin);
// freopen("cout.txt","w",stdout);
#endif
}
const int N=1e3+5;
vector<set<int> >G(N);
signed main()
{
// IOS;
//file();
int n,x;
scanf("%d",&n);
for(int i=1;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
G[x].insert(y);
G[y].insert(x);
}
for(int k=0;k<n/2;k++)
{
vector<int>vec;
for(int i=1;i<=n;i++)
{
if(G[i].size()==1)
vec.pb(i);
}
printf("? %d %d\n",vec[0],vec[1]);
fflush(stdout);
scanf("%d",&x);
if(vec[0]!=x)
{
int num=*G[vec[0]].begin();
G[num].erase(vec[0]);
G[vec[0]].erase(num);
}
if(vec[1]!=x)
{
int num=*G[vec[1]].begin();
G[num].erase(vec[1]);
G[vec[1]].erase(num);
}
}
printf("! %d\n",x);
fflush(stdout);
return 0;
}