https://codeforces.com/contest/1305/problem/D
题意:给出一棵n个节点的树,让我们确定哪一点为根;
我们可以询问任意选择其中两个节点,然后系统得出哪个节点为他们的lca
当已经知道答案后,就可以不再选择节点直接输出根节点,当还无法确定答案的时候,就继续询问;
思路:我们将所有一度的节点放进set,然后遍历一度的节点;
倘若得出的lac为两节点中其中一个,则为答案;
倘若lca是其他节点,则继续询问,然后将这两个点所连接的其他点的入度减一;
执行到完,便能得出答案
1 #include<bits/stdc++.h> 2 #define ll long long 3 #define inf 0x3f3f3f3f 4 #define mod 1000000007 5 #define PI acos(-1) 6 #define fi first 7 #define se second 8 #define lowbit(x) (x&(-x)) 9 #define mp make_pair 10 #define pb push_back 11 #define si size() 12 #define E exp(1.0) 13 #define fixed cout.setf(ios::fixed) 14 #define fixeds(x) setprecision(x) 15 using namespace std; 16 inline ll read(){ll s=0,w=1;char ch=getchar(); 17 while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();} 18 while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar(); 19 return s*w;}void put1(){ puts("Yes") ;}void put2(){ puts("No") ;} 20 void debug(){printf("T A T\n");}void put3(){ puts("-1"); }ll qpf(ll a, ll b, ll p) 21 {ll ret = 0;while(b){if(b & 1) ret = (ret + a) % p;a = (a + a) % p;b >>= 1;} 22 return ret % p ;}ll qp(ll a, ll n, ll p){ll ret = 1;while(n){if(n & 1) ret = qpf(ret, a, p); 23 a = qpf(a, a, p);n >>= 1;}return ret % p ;}//��=acos(L/2R); 24 const int manx=2e5+5; 25 ll d[manx]; 26 vector<ll>g[manx]; 27 set<ll>s; 28 void del(ll u){ 29 for(int i=0;i<g[u].size();i++){ 30 int v=g[u][i]; 31 d[v]--; 32 if(d[v]==1) s.insert(v); 33 } 34 } 35 void out(ll x){ 36 cout<<"! "<<x<<endl; cout.flush(); 37 } 38 int main() 39 { 40 ll n=read(); 41 for(int i=1;i<n;i++){ 42 ll u=read(),v=read(); 43 g[u].pb(v); 44 g[v].pb(u); 45 d[u]++,d[v]++; 46 } 47 for(int i=1;i<=n;i++) 48 if(d[i]==1) 49 s.insert(i); 50 while(s.si>1){ 51 ll u=*s.begin(),v=*(++s.begin()); 52 cout<<"? "<<u<<" "<<v<<endl; 53 cout.flush(); 54 ll lca; cin>>lca; 55 if(lca==u || lca==v){ 56 out(lca); 57 return 0; 58 } 59 del(u),del(v); 60 s.erase(u),s.erase(v); 61 } 62 out(*s.begin()); 63 return 0; 64 }