Problem: cf1044_b
Difficulty: medium
Categories: graph
Time limit: 2000 ms, memory limit: 256 MB

You are playing a strange game with Li Chen. You have a tree with $n$ nodes drawn on a piece of paper. All nodes are unlabeled and distinguishable. Each of you independently labeled the vertices from $1$ to $n$. Neither of you know the other's labelling of the tree.

You and Li Chen each chose a subtree (i.e., a connected subgraph) in that tree. Your subtree consists of the vertices labeled $x_1, x_2, \ldots, x_{k_1}$ in your labeling, Li Chen's subtree consists of the vertices labeled $y_1, y_2, \ldots, y_{k_2}$ in his labeling. The values of $x_1, x_2, \ldots, x_{k_1}$ and $y_1, y_2, \ldots, y_{k_2}$ are known to both of you.

 ![](https://espresso.codeforces.com/0defd3cbb822fdde342d5b0b173f9a1de22eaafc.png)  The picture shows two labelings of a possible tree: yours on the left and Li Chen's on the right. The selected trees are highlighted. There are two common nodes. 

You want to determine whether your subtrees have at least one common vertex. Luckily, your friend Andrew knows both labelings of the tree. You can ask Andrew at most $5$ questions, each of which is in one of the following two forms:

* A x: Andrew will look at vertex $x$ in your labeling and tell you the number of this vertex in Li Chen's labeling.
* B y: Andrew will look at vertex $y$ in Li Chen's labeling and tell you the number of this vertex in your labeling.

Determine whether the two subtrees have at least one common vertex after asking some questions. If there is at least one common vertex, determine one of your labels for any of the common vertices.

Interaction

Each test consists of several test cases.

The first line of input contains a single integer $t$ ($1 \leq t \leq 100$) — the number of test cases.

For each testcase, your program should interact in the following format.

The first line contains a single integer $n$ ($1 \leq n \leq 1\,000$) — the number of nodes in the tree.

Each of the next $n-1$ lines contains two integers $a_i$ and $b_i$ ($1\leq a_i, b_i\leq n$) — the edges of the tree, indicating an edge between node $a_i$ and $b_i$ according to your labeling of the nodes.

The next line contains a single integer $k_1$ ($1 \leq k_1 \leq n$) — the number of nodes in your subtree.

The next line contains $k_1$ distinct integers $x_1,x_2,\ldots,x_{k_1}$ ($1 \leq x_i \leq n$) — the indices of the nodes in your subtree, according to your labeling. It is guaranteed that these vertices form a subtree.

The next line contains a single integer $k_2$ ($1 \leq k_2 \leq n$) — the number of nodes in Li Chen's subtree.

The next line contains $k_2$ distinct integers $y_1, y_2, \ldots, y_{k_2}$ ($1 \leq y_i \leq n$) — the indices (according to Li Chen's labeling) of the nodes in Li Chen's subtree. It is guaranteed that these vertices form a subtree according to Li Chen's labelling of the tree's nodes.

Test cases will be provided one by one, so you must complete interacting with the previous test (i.e. by printing out a common node or $-1$ if there is not such node) to start receiving the next one.

You can ask the Andrew two different types of questions.

* You can print "A x" ($1 \leq x \leq n$). Andrew will look at vertex $x$ in your labeling and respond to you with the number of this vertex in Li Chen's labeling.
* You can print "B y" ($1 \leq y \leq n$). Andrew will look at vertex $y$ in Li Chen's labeling and respond to you with the number of this vertex in your labeling.

You may only ask at most $5$ questions per tree.

When you are ready to answer, print "C s", where $s$ is your label of a vertex that is common to both subtrees, or $-1$, if no such vertex exists. Printing the answer does not count as a question. Remember to flush your answer to start receiving the next test case.

After printing a question do not forget to print end of line and flush the output. Otherwise, you will get Idleness limit exceeded. To do this, use:

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

If the judge responds with $-1$, it means that you asked more queries than allowed, or asked an invalid query. Your program should immediately terminate (for example, by calling exit(0)). You will receive Wrong Answer; it means that you asked more queries than allowed, or asked an invalid query. If you ignore this, you can get other verdicts since your program will continue to read from a closed stream.

Examples

Input

```
1  
3  
1 2  
2 3  
1  
1  
1  
2  
2  
1
```

Output

```
A 1  
B 2  
C 1
```

Input

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

Output

```
B 2  
C 1  
A 1  
C -1
```

Note

For the first sample, Li Chen's hidden permutation is $[2, 3, 1]$, and for the second, his hidden permutation is $[5, 3, 2, 4, 1, 6]$ for both cases.

In the first sample, there is a tree with three nodes in a line. On the top, is how you labeled the tree and the subtree you chose, and the bottom is how Li Chen labeled the tree and the subtree he chose:

 ![](https://espresso.codeforces.com/fd10a54c6cc10884aa7fb708a2cbf6d3cb4daa29.png) 

In the first question, you ask Andrew to look at node $1$ in your labelling and tell you the label of it in Li Chen's labelling. Andrew responds with $2$. At this point, you know that both of your subtrees contain the same node (i.e. node $1$ according to your labeling), so you can output "C 1" and finish. However, you can also ask Andrew to look at node $2$ in Li Chen's labelling and tell you the label of it in your labelling. Andrew responds with $1$ (this step was given with the only reason — to show you how to ask questions).

For the second sample, there are two test cases. The first looks is the one from the statement:

 ![](https://espresso.codeforces.com/6e657baf0e89b8da496fe553b22e3f133bb24d85.png) 

We first ask "B 2", and Andrew will tell us $3$. In this case, we know $3$ is a common vertex, and moreover, any subtree with size $3$ that contains node $3$ must contain node $1$ as well, so we can output either "C 1" or "C 3" as our answer.

In the second case in the second sample, the situation looks as follows:

 ![](https://espresso.codeforces.com/4caafc9d13cebf999fafcd0415c5a1acc5f3c908.png) 

In this case, you know that the only subtree of size $3$ that doesn't contain node $1$ is subtree $4,5,6$. You ask Andrew for the label of node $1$ in Li Chen's labelling and Andrew says $5$. In this case, you know that Li Chen's subtree doesn't contain node $1$, so his subtree must be consist of the nodes $4,5,6$ (in your labelling), thus the two subtrees have no common nodes.

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


static int max_queries = 0; 
static int queries_limit = 5; 



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


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

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

    
    int t = inf.readInt();
    cout << t << endl; 

    for (int test_idx = 1; test_idx <= t; ++test_idx) {
        
        int n = inf.readInt();
        vector<pair<int, int>> edges;
        for (int i = 0; i < n - 1; ++i) {
            int u = inf.readInt();
            int v = inf.readInt();
            edges.push_back({u, v});
        }
        
        int k1 = inf.readInt();
        vector<int> s1; 
        for (int i = 0; i < k1; ++i) s1.push_back(inf.readInt());
        
        int k2 = inf.readInt();
        vector<int> s2; 
        for (int i = 0; i < k2; ++i) s2.push_back(inf.readInt());
        
        
        
        vector<int> p(n);
        vector<int> inv_p(n + 1); 
        for (int i = 0; i < n; ++i) {
            p[i] = inf.readInt();
            inv_p[p[i]] = i + 1;
        }

        
        cout << n << endl;
        for (auto &e : edges) cout << e.first << " " << e.second << endl;
        
        cout << k1 << endl;
        for (int i = 0; i < k1; ++i) cout << s1[i] << (i == k1 - 1 ? "" : " ");
        cout << endl;
        
        cout << k2 << endl;
        for (int i = 0; i < k2; ++i) cout << s2[i] << (i == k2 - 1 ? "" : " ");
        cout << endl;
        cout.flush();
        
        
        log_metrics();

        
        int current_queries = 0;
        
        while (true) {
            string type;
            if (!(cin >> type)) {
                finish(_wa, "Unexpected EOF (contestant output ended early)");
            }
            
            
            if (type == "?" || type == "!") {
                if (!(cin >> type)) finish(_wa, "Unexpected EOF after prefix");
            }
            
            if (type == "A") {
                
                if (current_queries >= 5) {
                    cout << -1 << endl; 
                    finish(_wa, "Query limit exceeded (5)");
                }
                
                int x;
                if (!(cin >> x)) finish(_wa, "Expected integer after A");
                
                if (x < 1 || x > n) {
                    cout << -1 << endl;
                    finish(_wa, format("Invalid query A %d (n=%d)", x, n));
                }
                
                current_queries++;
                if (current_queries > max_queries) {
                    max_queries = current_queries;
                    log_metrics();
                }
                
                cout << p[x - 1] << endl;
                cout.flush();
                
            } else if (type == "B") {
                
                if (current_queries >= 5) {
                    cout << -1 << endl;
                    finish(_wa, "Query limit exceeded (5)");
                }
                
                int y;
                if (!(cin >> y)) finish(_wa, "Expected integer after B");
                
                if (y < 1 || y > n) {
                    cout << -1 << endl;
                    finish(_wa, format("Invalid query B %d (n=%d)", y, n));
                }
                
                current_queries++;
                if (current_queries > max_queries) {
                    max_queries = current_queries;
                    log_metrics();
                }
                
                cout << inv_p[y] << endl;
                cout.flush();
                
            } else if (type == "C") {
                
                int s;
                if (!(cin >> s)) finish(_wa, "Expected integer after C");
                
                
                set<int> set_s2(s2.begin(), s2.end());
                bool intersection_exists = false;
                for (int u : s1) {
                    
                    if (set_s2.count(p[u - 1])) {
                        intersection_exists = true;
                        break;
                    }
                }
                
                if (s == -1) {
                    if (intersection_exists) {
                        finish(_wa, "Contestant claimed disjoint (-1), but intersection exists");
                    }
                } else {
                    
                    bool in_s1 = false;
                    for (int u : s1) if (u == s) in_s1 = true;
                    
                    if (!in_s1) {
                        finish(_wa, format("Output vertex %d is not in your subtree S1", s));
                    }
                    
                    if (s < 1 || s > n) {
                        finish(_wa, format("Output vertex %d out of range", s));
                    }
                    
                    
                    if (!set_s2.count(p[s - 1])) {
                        finish(_wa, format("Vertex %d maps to %d (opponent), which is not in S2", s, p[s - 1]));
                    }
                }
                
                
                break; 
                
            } else {
                finish(_wa, "Unknown query type: " + type);
            }
        }
    }
    
    finish(_ok, "All cases passed");
    return 0;
}


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

using namespace std;




static int max_queries_seen = 0;
static const int QUERY_LIMIT_VAL = 5;


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


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

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

    
    int t = inf.readInt();
    cout << t << endl; 

    
    while (t--) {
        
        int n = inf.readInt();
        vector<pair<int, int>> edges;
        for (int i = 0; i < n - 1; ++i) {
            int u = inf.readInt();
            int v = inf.readInt();
            edges.push_back({u, v});
        }

        int k1 = inf.readInt();
        vector<int> s1(k1);
        for (int i = 0; i < k1; ++i) s1[i] = inf.readInt();

        int k2 = inf.readInt();
        vector<int> s2(k2);
        for (int i = 0; i < k2; ++i) s2[i] = inf.readInt();

        
        
        
        vector<int> p(n);
        vector<int> inv_p(n + 1); 
        for (int i = 0; i < n; ++i) {
            p[i] = inf.readInt();
            inv_p[p[i]] = i + 1;
        }

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

        cout << k1 << endl;
        for (int i = 0; i < k1; ++i) {
            cout << s1[i] << (i == k1 - 1 ? "" : " ");
        }
        cout << endl;

        cout << k2 << endl;
        for (int i = 0; i < k2; ++i) {
            cout << s2[i] << (i == k2 - 1 ? "" : " ");
        }
        cout << endl;
        
        
        cout.flush();

        
        int queries_this_case = 0;
        set<int> set1(s1.begin(), s1.end());
        set<int> set2(s2.begin(), s2.end());

        
        if (max_queries_seen == 0) log_metrics();

        bool case_active = true;
        while (case_active) {
            string type;
            
            if (!(cin >> type)) {
                finish(_pe, "Unexpected EOF while waiting for query/answer");
            }

            if (type == "A") {
                int x;
                if (!(cin >> x)) finish(_pe, "Expected integer after A");

                queries_this_case++;
                max_queries_seen = max(max_queries_seen, queries_this_case);

                
                if (queries_this_case > 200) {
                    finish(_pe, "Hard query limit exceeded (>200)");
                }

                if (x < 1 || x > n) {
                    finish(_wa, "Query A: index out of range");
                }

                cout << p[x - 1] << endl; 
            } 
            else if (type == "B") {
                int y;
                if (!(cin >> y)) finish(_pe, "Expected integer after B");

                queries_this_case++;
                max_queries_seen = max(max_queries_seen, queries_this_case);

                if (queries_this_case > 200) {
                    finish(_pe, "Hard query limit exceeded (>200)");
                }

                if (y < 1 || y > n) {
                    finish(_wa, "Query B: index out of range");
                }

                cout << inv_p[y] << endl;
            } 
            else if (type == "C") {
                int s;
                if (!(cin >> s)) finish(_pe, "Expected integer after C");

                
                bool intersection_exists = false;
                for (int u : s1) {
                    
                    if (set2.count(p[u - 1])) {
                        intersection_exists = true;
                        break;
                    }
                }

                if (s == -1) {
                    if (intersection_exists) {
                        finish(_wa, "Contestant answered -1 but intersection exists");
                    }
                } else {
                    if (!intersection_exists) {
                        finish(_wa, "Contestant returned node but no intersection exists");
                    }
                    if (s < 1 || s > n) {
                        finish(_wa, "Answer index out of range");
                    }
                    if (!set1.count(s)) {
                        finish(_wa, "Answer node not in your subtree (S1)");
                    }
                    if (!set2.count(p[s - 1])) {
                        finish(_wa, "Answer node corresponds to node not in Li Chen's subtree (S2)");
                    }
                }

                
                case_active = false;
            } 
            else {
                finish(_pe, "Invalid query type: " + type);
            }
        }
    }

    finish(_ok, "All test cases passed");
}


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

using namespace std;


























vector<pair<int, int>> genTree(int n) {
    vector<pair<int, int>> edges;
    if (n == 1) return edges;

    int type = rnd.next(1, 10);
    
    
    
    
    
    if (type <= 6) {
        
        
        
        vector<pair<int, int>> temp_edges;
        for (int i = 2; i <= n; i++) {
            temp_edges.push_back({rnd.next(1, i - 1), i});
        }
        
        
        vector<int> p(n);
        iota(p.begin(), p.end(), 1);
        shuffle(p.begin(), p.end());
        
        for (auto &e : temp_edges) {
            edges.push_back({p[e.first - 1], p[e.second - 1]});
        }
    } else if (type <= 8) {
        
        vector<int> p(n);
        iota(p.begin(), p.end(), 1);
        shuffle(p.begin(), p.end());
        for (int i = 0; i < n - 1; ++i) {
            edges.push_back({p[i], p[i + 1]});
        }
    } else {
        
        vector<int> p(n);
        iota(p.begin(), p.end(), 1);
        shuffle(p.begin(), p.end());
        int center = p[0];
        for (int i = 1; i < n; ++i) {
            edges.push_back({p[i], center});
        }
    }
    return edges;
}



vector<int> genSubtree(int n, const vector<vector<int>>& adj, int size, const vector<int>& restriction = {}) {
    if (size == n && restriction.empty()) {
        vector<int> res(n);
        iota(res.begin(), res.end(), 1);
        return res;
    }

    vector<bool> allowed(n + 1, true);
    if (!restriction.empty()) {
        fill(allowed.begin(), allowed.end(), false);
        for (int x : restriction) allowed[x] = true;
    }

    
    vector<int> candidates;
    for (int i = 1; i <= n; i++) if (allowed[i]) candidates.push_back(i);
    
    if (candidates.empty()) return {}; 

    int root = candidates[rnd.next(0, (int)candidates.size() - 1)];
    vector<int> sub;
    sub.push_back(root);
    
    vector<bool> inSub(n + 1, false);
    inSub[root] = true;
    
    
    set<int> boundary;
    for (int v : adj[root]) {
        if (allowed[v]) boundary.insert(v);
    }
    
    while ((int)sub.size() < size && !boundary.empty()) {
        int idx = rnd.next(0, (int)boundary.size() - 1);
        auto it = boundary.begin();
        advance(it, idx);
        int v = *it;
        boundary.erase(it);
        
        inSub[v] = true;
        sub.push_back(v);
        
        for (int u : adj[v]) {
            if (allowed[u] && !inSub[u]) {
                boundary.insert(u);
            }
        }
    }
    return sub;
}

int main(int argc, char* argv[]) {
    registerGen(argc, argv, 1);
    
    string mode = opt<string>("mode", "non");
    int tOpt = opt<int>("t", -1);
    int budgetOpt = opt<int>("sum_n", -1);

    int seed = atoi(argv[1]);

    int t;
    if (tOpt != -1) {
        t = tOpt;
    } else if (mode == "adp") {
        
        t = (seed % 3 == 0) ? 25 : rnd.next(5, 15);
    } else {
        if (seed == 1) t = 1;
        else if (seed == 2) t = 2;
        else t = rnd.next(3, 10);
    }
    t = max(1, min(100, t));

    int sum_budget;
    if (budgetOpt != -1) sum_budget = budgetOpt;
    else sum_budget = (mode == "adp" ? 9000 : 6000);
    sum_budget = max(2 * t, sum_budget); 

    
    vector<int> ns;
    ns.reserve(t);
    int remaining = sum_budget;
    for (int i = 0; i < t; i++) {
        int min_n = 2;
        if (seed == 1 && i == 0) min_n = 1; 
        int min_left = (t - i - 1) * 2;
        int hi = min(1000, remaining - min_left);
        if (hi < min_n) hi = min_n;

        int n;
        if (mode == "adp") {
            
            int lo = min(hi, max(min_n, 700));
            n = rnd.next(lo, hi);
        } else {
            int type = rnd.next(1, 100);
            if (type <= 10) n = rnd.next(min_n, min(hi, 10));
            else if (type <= 30) n = rnd.next(min_n, min(hi, 100));
            else n = rnd.next(min_n, hi);
        }
        ns.push_back(n);
        remaining -= n;
    }

    cout << t << endl;

    for (int test_idx = 0; test_idx < t; test_idx++) {
        int n = ns[test_idx];

        vector<pair<int, int>> edges = genTree(n);
        vector<vector<int>> adj(n + 1);
        for (auto e : edges) {
            adj[e.first].push_back(e.second);
            adj[e.second].push_back(e.first);
        }

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

        
        int k1;
        if (n == 1) k1 = 1;
        else if (mode == "adp") k1 = rnd.next(1, max(1, n / 2)); 
        else k1 = rnd.next(1, n);

        vector<int> s1 = genSubtree(n, adj, k1);
        cout << (int)s1.size() << endl;
        for (int i = 0; i < (int)s1.size(); i++) cout << s1[i] << (i == (int)s1.size() - 1 ? "" : " ");
        cout << endl;

        
        vector<int> s2_p1;

        
        int rel = rnd.next(1, 100);
        bool disjoint = false;
        if (mode == "adp") {
            
            if (rel <= 60) disjoint = true;
        } else {
            if (rel <= 40) disjoint = true;
        }

        vector<bool> inS1(n + 1, false);
        for (int x : s1) inS1[x] = true;

        if (disjoint) {
            
            vector<int> outside;
            for (int i = 1; i <= n; i++) if (!inS1[i]) outside.push_back(i);

            if (outside.empty()) {
                
                s2_p1 = genSubtree(n, adj, rnd.next(1, n));
            } else {
                int max_k2 = (int)outside.size();
                int k2 = rnd.next(1, max_k2);
                s2_p1 = genSubtree(n, adj, k2, outside);
            }
        } else {
            
            int choice = rnd.next(1, 2);
            if (choice == 1) {
                
                s2_p1 = genSubtree(n, adj, rnd.next(1, n));
            } else {
                
                int root = s1[rnd.next(0, (int)s1.size() - 1)];
                int k2 = rnd.next(1, n);

                
                s2_p1.push_back(root);
                vector<bool> inS2(n + 1, false);
                inS2[root] = true;
                set<int> boundary;
                for (int v : adj[root]) boundary.insert(v);

                while ((int)s2_p1.size() < k2 && !boundary.empty()) {
                    int idx = rnd.next(0, (int)boundary.size() - 1);
                    auto it = boundary.begin();
                    advance(it, idx);
                    int v = *it;
                    boundary.erase(it);
                    inS2[v] = true;
                    s2_p1.push_back(v);
                    for (int u : adj[v]) if (!inS2[u]) boundary.insert(u);
                }
            }
        }

        
        vector<int> p = rnd.perm(n, 1);

        
        vector<int> s2_p2;
        for (int x : s2_p1) s2_p2.push_back(p[x - 1]);

        cout << (int)s2_p2.size() << endl;
        for (int i = 0; i < (int)s2_p2.size(); i++) cout << s2_p2[i] << (i == (int)s2_p2.size() - 1 ? "" : " ");
        cout << endl;

        
        for (int i = 0; i < n; i++) cout << p[i] << (i == n - 1 ? "" : " ");
        cout << endl;
    }

    return 0;
}