Problem: cf1444_e
Difficulty: medium
Categories: graph, game, bit, greedy
Time limit: 1000 ms, memory limit: 512 MB

This is an interactive problem.

You are given a tree — connected undirected graph without cycles. One vertex of the tree is special, and you have to find which one. You can ask questions in the following form: given an edge of the tree, which endpoint is closer to the special vertex, meaning which endpoint's shortest path to the special vertex contains fewer edges. You have to find the special vertex by asking the minimum number of questions in the worst case for a given tree.

Please note that the special vertex might not be fixed by the interactor in advance: it might change the vertex to any other one, with the requirement of being consistent with the previously given answers.

Input

You are given an integer $n$ ($2 \le n \le 100$) — the number of vertices in a tree.

The folloiwing $n-1$ lines contain two integers each, $u$ and $v$ ($1 \le u, v \le n$), that denote an edge in the tree connecting $u$ and $v$. It is guaranteed that the given edges form a tree.

Interaction

After reading the input data, one can start making queries. There are two possible queries:

1. "? $u$ $v$" — to ask for an edge $(u, v)$ ($1 \le u, v \le n$) which of the endpoints is closer to the special vertex. The answer to this query is one of the endpoints. Note that, $u$ and $v$ must be connected by an edge, and hence they can not have the same distance to the special vertex.
2. "! $u$" — to indicate that you found the special vertex. After the program does that, it must immediately terminate.

Do not forget to output the end of line and flush the output. Otherwise you will get Idleness limit exceeded verdict. To flush the output, you can use:

* fflush(stdout) or cout.flush() in C++;
* System.out.flush() in Java;
* flush(output) in Pascal;
* sys.stdout.flush() in Python;
* see documentation for other languages.

In case you ask more queries than needed in the worst case for a given tree, you will get verdict Wrong answer.

Examples

Input

```
5
1 2
2 3
3 4
4 5
3
2
1
```

Output

```
? 3 4
? 2 3
? 1 2
! 1
```

Input

```
5
2 1
3 1
4 1
5 1
1
1
4
```

Output

```
? 1 2
? 1 3
? 1 4
! 4
```

Note

Non-adaptive interactor (C++):
#include "testlib.h"
#include <bits/stdc++.h>
using namespace std;




static int queries = 0;
static int query_limit = 0;
static const int HARD_CAP = 2000; 
static int N;
static vector<vector<int>> adj;
static int target = -1;
static set<pair<int, int>> edges_set;






void log_metrics() {
    try {
        tout << "queries=" << queries << endl;
        tout << "query_limit=" << query_limit << endl;
    } catch (...) {
        
    }
}


template <typename... Args>
void finish(TResult verdict, const char* fmt, Args... args) {
    log_metrics();
    quitf(verdict, fmt, args...);
}






















vector<int> compute_dp(int u, int p, int& max_label) {
    vector<vector<int>> children_S;
    for (int v : adj[u]) {
        if (v == p) continue;
        children_S.push_back(compute_dp(v, u, max_label));
    }
    
    
    sort(children_S.begin(), children_S.end(), [](const vector<int>& a, const vector<int>& b) {
        return a > b; 
    });
    
    vector<int> current_S; 
    
    for (const auto& S_v : children_S) {
        int w = 1;
        while (true) {
            
            bool in_Sv = false;
            for (int r : S_v) {
                if (r == w) { in_Sv = true; break; }
            }
            if (in_Sv) {
                w++;
                continue;
            }
            
            
            
            vector<int> exposed;
            exposed.push_back(w);
            for (int r : S_v) {
                if (r > w) exposed.push_back(r);
            }
            
            
            bool clash = false;
            for (int e : exposed) {
                for (int s : current_S) {
                    if (e == s) {
                        clash = true;
                        break;
                    }
                }
                if (clash) break;
            }
            
            if (!clash) {
                
                if (w > max_label) max_label = w;
                
                for (int e : exposed) current_S.push_back(e);
                break;
            }
            w++;
        }
    }
    
    
    sort(current_S.rbegin(), current_S.rend());
    return current_S;
}

int calc_limit() {
    if (N < 2) return 0;
    int max_label = 0;
    compute_dp(1, -1, max_label);
    return max_label;
}




int get_dist(int start, int end_node) {
    if (start == end_node) return 0;
    queue<pair<int, int>> q;
    q.push({start, 0});
    vector<int> visited(N + 1, 0);
    visited[start] = 1;
    
    while (!q.empty()) {
        auto [u, d] = q.front();
        q.pop();
        if (u == end_node) return d;
        for (int v : adj[u]) {
            if (!visited[v]) {
                visited[v] = 1;
                q.push({v, d + 1});
            }
        }
    }
    return 1e9; 
}




int main(int argc, char** argv) {
    registerInteraction(argc, argv);
    atexit(log_metrics);

    
    N = inf.readInt(2, 100, "n");
    adj.resize(N + 1);
    for (int i = 0; i < N - 1; ++i) {
        int u = inf.readInt(1, N, "u");
        int v = inf.readInt(1, N, "v");
        adj[u].push_back(v);
        adj[v].push_back(u);
        if (u > v) swap(u, v);
        edges_set.insert({u, v});
    }
    
    target = inf.readInt(1, N, "target");

    
    query_limit = calc_limit();
    log_metrics(); 

    
    cout << N << endl;
    for (auto e : edges_set) {
        cout << e.first << " " << e.second << endl;
    }
    cout.flush();

    
    while (true) {
        
        if (queries > HARD_CAP) {
            finish(_pe, "Hard query limit exceeded (%d)", HARD_CAP);
        }

        string token;
        cin >> token;
        if (cin.fail()) {
            finish(_pe, "Unexpected EOF or read error");
        }

        if (token == "!") {
            int guess;
            cin >> guess;
            if (cin.fail()) finish(_pe, "Expected integer after '!'");
            
            if (guess == target) {
                finish(_ok, "Correct! Found %d in %d queries (limit %d)", target, queries, query_limit);
            } else {
                finish(_wa, "Wrong guess: %d. Expected: %d", guess, target);
            }
        } else {
            
            int u, v;
            if (token == "?") {
                cin >> u >> v;
            } else {
                
                try {
                    u = stoi(token);
                } catch (...) {
                    finish(_pe, "Invalid token '%s'", token.c_str());
                }
                cin >> v;
            }
            if (cin.fail()) finish(_pe, "Invalid query format");

            
            if (u < 1 || u > N || v < 1 || v > N) {
                finish(_pe, "Vertices %d %d out of range [1, %d]", u, v, N);
            }
            int u_sorted = min(u, v);
            int v_sorted = max(u, v);
            if (edges_set.find({u_sorted, v_sorted}) == edges_set.end()) {
                finish(_pe, "Vertices %d and %d are not connected by an edge", u, v);
            }

            
            queries++;
            
            if (queries % 10 == 0) log_metrics();

            int dist_u = get_dist(u, target);
            int dist_v = get_dist(v, target);

            
            if (dist_u == dist_v) {
                finish(_pe, "Logic error: equal distance in tree");
            }

            int ans = (dist_u < dist_v ? u : v);
            cout << ans << endl;
        }
    }

    return 0;
}


Adaptive interactor (C++):
#include "testlib.h"
#include <bits/stdc++.h>

using namespace std;


























int n;
vector<vector<int>> adj;
vector<bool> candidates;
int candidates_count = 0;


static long long queries = 0;
static long long query_limit = 0;

static void log_metrics() {
    try {
        tout << "queries=" << queries << endl;
        tout << "query_limit=" << query_limit << endl;
    } catch (...) {
        
    }
}

static void finish(TResult verdict, const string& msg) {
    log_metrics();
    quitf(verdict, "%s", msg.c_str());
}


vector<int> get_dists(int start) {
    vector<int> d(n + 1, -1);
    queue<int> q;
    q.push(start);
    d[start] = 0;
    
    while (!q.empty()) {
        int u = q.front();
        q.pop();
        for (int v : adj[u]) {
            if (d[v] == -1) {
                d[v] = d[u] + 1;
                q.push(v);
            }
        }
    }
    return d;
}

int main(int argc, char** argv) {
    
    registerInteraction(argc, argv);
    atexit(log_metrics);

    
    n = inf.readInt();
    adj.resize(n + 1);
    vector<pair<int, int>> edges_list;
    for (int i = 0; i < n - 1; ++i) {
        int u = inf.readInt();
        int v = inf.readInt();
        adj[u].push_back(v);
        adj[v].push_back(u);
        edges_list.push_back({u, v});
    }

    
    
    query_limit = n;

    
    cout << n << endl;
    for (auto& e : edges_list) {
        cout << e.first << " " << e.second << endl;
    }
    cout.flush();

    
    candidates.assign(n + 1, true);
    candidates_count = n;
    
    
    log_metrics();

    
    while (true) {
        string type;
        
        
        int c = cin.peek();
        while (c != EOF && isspace(c)) {
            cin.get();
            c = cin.peek();
        }
        if (c == EOF) {
            finish(_pe, "Unexpected EOF from contestant");
        }

        cin >> type;

        if (type == "!") {
            int guess;
            if (!(cin >> guess)) finish(_pe, "Invalid format for answer");

            
            if (guess < 1 || guess > n) finish(_wa, "Guess out of range");

            
            if (!candidates[guess]) {
                finish(_wa, "Guess is inconsistent with previous query answers");
            }

            
            if (candidates_count > 1) {
                finish(_wa, "Special vertex not uniquely identified; more queries needed");
            }

            finish(_ok, "Correct");
        }
        else if (type == "?") {
            int u, v;
            if (!(cin >> u >> v)) finish(_pe, "Invalid format for query");

            
            if (u < 1 || u > n || v < 1 || v > n) finish(_wa, "Query vertices out of range");
            
            bool edge_exists = false;
            for (int nb : adj[u]) {
                if (nb == v) {
                    edge_exists = true;
                    break;
                }
            }
            if (!edge_exists) finish(_wa, "Query edge does not exist");

            queries++;
            
            if (queries > 200000) finish(_pe, "Too many queries (hard cap exceeded)");

            
            
            vector<int> dist_u = get_dists(u);
            vector<int> dist_v = get_dists(v);

            int count_u = 0;
            int count_v = 0;
            vector<int> list_u, list_v;

            for (int i = 1; i <= n; ++i) {
                if (candidates[i]) {
                    if (dist_u[i] < dist_v[i]) {
                        count_u++;
                        list_u.push_back(i);
                    } else {
                        count_v++;
                        list_v.push_back(i);
                    }
                }
            }

            int reply = -1;
            
            if (count_u >= count_v) {
                reply = u;
                
                for (int x : list_v) candidates[x] = false;
                candidates_count = count_u;
            } else {
                reply = v;
                
                for (int x : list_u) candidates[x] = false;
                candidates_count = count_v;
            }

            
            if (candidates_count == 0) {
                finish(_wa, "Inconsistent state (interactor internal error)");
            }

            cout << reply << endl;
        }
        else {
            finish(_pe, "Invalid query type (expected '?' or '!')");
        }
    }

    return 0;
}


Test generator (C++):
#include "testlib.h"
#include <bits/stdc++.h>

using namespace std;

int main(int argc, char* argv[]) {
    
    registerGen(argc, argv, 1);

    
    
    string mode = opt<string>("mode", "non");
    
    int n = opt<int>("n", -1);
    
    
    long long seed_val = atoll(argv[1]);
    string type = "random";

    if (n == -1) {
        if (seed_val == 1) { n = 2; type = "random"; }
        else if (seed_val == 2) { n = 3; type = "line"; }
        else if (seed_val == 3) { n = 100; type = "line"; }
        else if (seed_val == 4) { n = 100; type = "star"; }
        else if (seed_val == 5) { n = 100; type = "binary"; }
        else if (seed_val == 6) { n = 100; type = "caterpillar"; }
        else {
            
            n = rnd.next(90, 100); 
            if (rnd.next(5) == 0) n = rnd.next(2, 100); 

            
            int t = rnd.next(1, 100);
            if (t <= 40) type = "random";
            else if (t <= 50) type = "line";
            else if (t <= 60) type = "star";
            else if (t <= 75) type = "binary";
            else if (t <= 90) type = "caterpillar";
            else type = "deep";
        }
    }

    
    
    vector<pair<int, int>> edges;
    if (n == 2) {
        edges.push_back({1, 2});
    } else {
        if (type == "line") {
            for (int i = 1; i < n; ++i) edges.push_back({i, i + 1});
        }
        else if (type == "star") {
            for (int i = 2; i <= n; ++i) edges.push_back({1, i});
        }
        else if (type == "binary") {
            
            for (int i = 2; i <= n; ++i) edges.push_back({i / 2, i});
        }
        else if (type == "caterpillar") {
            
            int len = rnd.next(n / 2, n - 1);
            if (len < 1) len = 1; 
            
            for (int i = 1; i < len; ++i) edges.push_back({i, i + 1});
            
            for (int i = len + 1; i <= n; ++i) {
                int p = rnd.next(1, len);
                edges.push_back({p, i});
            }
        }
        else if (type == "deep") {
            
            for (int i = 2; i <= n; ++i) {
                int start = max(1, i - 2); 
                int p = rnd.next(start, i - 1);
                edges.push_back({p, i});
            }
        }
        else { 
            
            for (int i = 2; i <= n; ++i) {
                edges.push_back({rnd.next(1, i - 1), i});
            }
        }
    }

    
    vector<int> p(n + 1);
    iota(p.begin(), p.end(), 0);
    shuffle(p.begin() + 1, p.end());

    vector<pair<int, int>> final_edges;
    for (auto& e : edges) {
        final_edges.push_back({p[e.first], p[e.second]});
    }

    
    shuffle(final_edges.begin(), final_edges.end());

    
    println(n);
    for (auto& e : final_edges) {
        if (rnd.next(2)) println(e.first, e.second);
        else println(e.second, e.first);
    }

    
    
    
    if (mode == "non") {
        int target = rnd.next(1, n);
        println(target);
    }
    
    return 0;
}