Problem: cf1738_f
Difficulty: medium
Categories: graph, greedy, data structures
Time limit: 2000 ms, memory limit: 512 MB

This is an interactive problem.

Given a simple undirected graph with $n$ vertices numbered from $1$ to $n$, your task is to color all the vertices such that for every color $c$, the following conditions hold:

1. The set of vertices with color $c$ is connected;
2. $s_c \leq n_c^2$, where $n_c$ is the number of vertices with color $c$, and $s_c$ is the sum of degrees of vertices with color $c$.

It can be shown that there always exists a way to color all the vertices such that the above conditions hold.

Initially, you are only given the number $n$ of vertices and the degree of each vertex.

In each query, you can choose a vertex $u$. As a response, you will be given the $k$-th edge incident to $u$, if this is the $k$-th query on vertex $u$.

You are allowed to make at most $n$ queries.

An undirected graph is simple if it does not contain multiple edges or self-loops.

The degree of a vertex is the number of edges incident to it.

A set $S$ of vertices is connected if for every two different vertices $u, v \in S$, there is a path, which only passes through vertices in $S$, that connects $u$ and $v$. That is, there is a sequence of edges $(u_1, v_1), (u_2, v_2), \dots, (u_k, v_k)$ with $k \geq 1$ such that

1. $u_1 = u$, $v_k = v$, and $v_i = u_{i+1}$ for every $1 \leq i < k$; and
2. $u_k \in S$ and $v_k \in S$ for every $1 \leq i \leq k$.

Especially, a set containing only one vertex is connected.

Interaction

Each test contains multiple test cases. The first line contains an integer $t$ ($1 \leq t \leq 1000$) — the number of test cases. The following lines contain the description and the interactive section of each test case.

For each test case, you begin the interaction by reading an integer $n$ ($1\le n \le 1000$) in the first line, indicating the number of vertices in the graph.

The second line contains $n$ integers $d_1, d_2, \dots, d_n$ ($0 \leq d_i \leq n - 1$), where $d_i$ is the degree of vertex $i$.

To make a query on vertex $u$ ($1 \leq u \leq n$), you should output

* "? $u$"

in a separate line. If this is the $k$-th query on vertex $u$, vertex $e_{u, k}$ will be given in the next separate line, where $\left(u, e_{u, k}\right)$ is the $k$-th edge incident to vertex $u$. In case of $k > d_u$, define $e_{u, k} = -1$. You should make no more than $n$ "?" queries.

To give the answer, you should output

* "! $c_1$ $c_2$ $\dots$ $c_n$"

in a separate line, where $c_i$ ($1 \leq c_i \leq n$) is the color of vertex $i$. After that, your program should continue to the next test case, or terminate if this is the last test case.

It is guaranteed that the graph is a simple undirected graph.

It is guaranteed that the sum of $n$ over all test cases does not exceed $1000$.

In case your query format is invalid, or you have made more than $n$ "?" queries, you will receive Wrong Answer verdict.

After printing a query, do not forget to output 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.

Example

Input

```
1
5
2 2 2 2 0

2

4

2

4
```

Output

```
? 1

? 1

? 3

? 3

! 1 1 2 2 3
```

Note

In the example, there is only one test case.

In the test case, there are $n = 5$ vertices with vertices $1, 2, 3, 4$ of degree $2$ and vertex $5$ of degree $0$. It is obvious that vertex $5$ is isolated, i.e., it does not connect to any other vertices.

A possible interaction is shown in the sample input and output, where $4$ "?" queries are made on vertex $1$ twice and vertex $3$ twice. According to the responses to these queries, we know that each of vertex $1$ and vertex $3$ connects to two vertices $2$ and $4$.

A possible solution is shown in the sample output, where vertex $1$ and vertex $2$ are colored by $1$, vertex $3$ and vertex $4$ are colored by $2$, and vertex $5$ is colored by $3$. It can be seen that this solution satisfies the required conditions as follows.

* For color $c = 1$, vertex $1$ and vertex $2$ are connected. Moreover, $n_1 = 2$ and $s_1 = d_1 + d_2 = 2 + 2 = 4 \leq n_1^2 = 2^2 = 4$;
* For color $c = 2$, vertex $3$ and vertex $4$ are connected. Moreover, $n_2 = 2$ and $s_2 = d_3 + d_4 = 2 + 2 = 4 \leq n_2^2 = 2^2 = 4$;
* For color $c = 3$, there is only one vertex (vertex $5$) colored by $3$. Moreover, $n_3 = 1$ and $s_3 = d_5 = 0 \leq n_3^2 = 1^2 = 1$.

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


static long long queries = 0;
static long long query_limit = 0;
static const long long HARD_CAP = 200000; 


static 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...);
}


int n;
vector<vector<int>> adj;
vector<int> degree;
vector<int> vertex_query_count;

void solve_test_case() {
    
    n = inf.readInt(1, 1000, "n");
    
    int m = inf.readInt(0, n * (n - 1) / 2, "m");

    
    query_limit += n;
    
    
    log_metrics();

    
    adj.assign(n + 1, vector<int>());
    degree.assign(n + 1, 0);
    for (int i = 0; i < m; 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);
        degree[u]++;
        degree[v]++;
    }

    
    for (int i = 1; i <= n; i++) {
        sort(adj[i].begin(), adj[i].end());
    }

    
    
    cout << n << endl;
    for (int i = 1; i <= n; i++) {
        cout << degree[i] << (i == n ? "" : " ");
    }
    cout << endl; 

    
    vertex_query_count.assign(n + 1, 0);

    
    while (true) {
        if (queries > HARD_CAP) {
            finish(_pe, "Hard query limit exceeded (infinite loop?)");
        }

        string token;
        if (!(cin >> token)) {
            finish(_pe, "Unexpected EOF while waiting for query/answer");
        }

        if (token == "!") {
            
            
            vector<int> c(n + 1);
            vector<vector<int>> color_groups(n + 1);
            
            for (int i = 1; i <= n; i++) {
                string col_str;
                if (!(cin >> col_str)) {
                    finish(_pe, "Unexpected EOF reading color for vertex %d", i);
                }
                try {
                    c[i] = stoi(col_str);
                } catch (...) {
                    finish(_pe, "Invalid color format (not an integer)");
                }

                if (c[i] < 1 || c[i] > n) {
                    finish(_wa, "Color %d for vertex %d is out of range [1, %d]", c[i], i, n);
                }
                color_groups[c[i]].push_back(i);
            }

            
            for (int k = 1; k <= n; k++) {
                if (color_groups[k].empty()) continue;
                const auto& nodes = color_groups[k];

                
                if (nodes.size() > 1) {
                    unordered_set<int> node_set(nodes.begin(), nodes.end());
                    int visited_count = 0;
                    queue<int> q;
                    q.push(nodes[0]);
                    unordered_set<int> visited;
                    visited.insert(nodes[0]);
                    
                    while (!q.empty()) {
                        int u = q.front();
                        q.pop();
                        visited_count++;
                        for (int v : adj[u]) {
                            if (node_set.count(v) && !visited.count(v)) {
                                visited.insert(v);
                                q.push(v);
                            }
                        }
                    }
                    if (visited_count != (int)nodes.size()) {
                        finish(_wa, "Vertices with color %d are not connected", k);
                    }
                }

                
                long long sum_deg = 0;
                for (int u : nodes) {
                    sum_deg += degree[u];
                }
                long long size = nodes.size();
                if (sum_deg > size * size) {
                    finish(_wa, "Color %d: sum of degrees (%lld) exceeds size^2 (%lld)", k, sum_deg, size * size);
                }
            }

            
            return;
        
        } else {
            
            
            int u = -1;
            if (token == "?") {
                if (!(cin >> u)) {
                    finish(_pe, "Expected vertex index after '?'");
                }
            } else {
                try {
                    u = stoi(token);
                } catch (...) {
                    finish(_pe, "Invalid token '%s': expected '?' or '!' or vertex index", token.c_str());
                }
            }

            if (u < 1 || u > n) {
                finish(_wa, "Query vertex %d out of range [1, %d]", u, n);
            }

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

            vertex_query_count[u]++;
            int k = vertex_query_count[u];
            
            
            int neighbor = -1;
            if (k <= degree[u]) {
                
                neighbor = adj[u][k - 1];
            }
            cout << neighbor << endl; 
        }
    }
}

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

    
    int t = inf.readInt(1, 1000, "t");
    cout << t << endl; 

    while (t--) {
        solve_test_case();
    }

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


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


static long long total_queries = 0;
static long long total_limit = 0;
static bool metrics_logged = false;



static void log_metrics() {
    if (metrics_logged) return;
    metrics_logged = true;
    
    if (tout.is_open()) {
        tout << "queries=" << total_queries << endl;
        tout << "query_limit=" << total_limit << endl;
    }
}


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


static void on_exit() {
    log_metrics();
}

void solve() {
    
    int n = inf.readInt();
    int m = inf.readInt();
    
    
    vector<vector<int>> adj(n + 1);
    
    vector<int> deg(n + 1, 0);
    
    for (int i = 0; i < m; ++i) {
        int u = inf.readInt();
        int v = inf.readInt();
        
        if (u >= 1 && u <= n && v >= 1 && v <= n) {
            adj[u].push_back(v);
            adj[v].push_back(u);
        }
    }

    
    for (int i = 1; i <= n; ++i) {
        deg[i] = adj[i].size();
    }

    
    cout << n << endl;
    for (int i = 1; i <= n; ++i) {
        cout << deg[i] << (i == n ? "" : " ");
    }
    cout << endl; 
    
    
    total_limit += n;
    
    int local_queries = 0;
    int limit = n; 

    
    vector<int> asked(n + 1, 0);

    
    while (true) {
        string type;
        if (!(cin >> type)) {
            finish(_pe, "Unexpected EOF from contestant");
        }

        if (type == "!") {
            
            vector<int> colors(n + 1);
            for (int i = 1; i <= n; ++i) {
                if (!(cin >> colors[i])) {
                    finish(_pe, "Cannot read colors");
                }
                if (colors[i] < 1 || colors[i] > n) {
                    finish(_wa, "Color index out of range [1, n]");
                }
            }
            
            
            
            map<int, vector<int>> groups;
            for (int i = 1; i <= n; ++i) {
                groups[colors[i]].push_back(i);
            }

            for (auto& entry : groups) {
                int c = entry.first;
                vector<int>& nodes = entry.second;
                if (nodes.empty()) continue;
                
                
                
                set<int> node_set(nodes.begin(), nodes.end());
                queue<int> q;
                q.push(nodes[0]);
                set<int> visited;
                visited.insert(nodes[0]);
                
                while(!q.empty()) {
                    int u = q.front(); q.pop();
                    for (int v : adj[u]) {
                        
                        if (node_set.count(v) && !visited.count(v)) {
                            visited.insert(v);
                            q.push(v);
                        }
                    }
                }
                
                if ((int)visited.size() != (int)nodes.size()) {
                    finish(_wa, "Color " + to_string(c) + " is not connected");
                }

                
                
                long long sum_deg = 0;
                for (int u : nodes) {
                    sum_deg += deg[u];
                }
                long long nc = nodes.size();
                if (sum_deg > nc * nc) {
                    finish(_wa, "Color " + to_string(c) + " violates degree condition: s_c=" + to_string(sum_deg) + " > n_c^2=" + to_string(nc*nc));
                }
            }
            
            
            return;

        } else if (type == "?") {
            int u;
            if (!(cin >> u)) finish(_pe, "Invalid query format");
            
            total_queries++;
            local_queries++;
            
            
            
            if (local_queries > limit) {
                finish(_wa, "Too many queries");
            }
            
            if (u < 1 || u > n) {
                finish(_wa, "Invalid vertex index in query");
            }

            
            int k = asked[u];
            asked[u]++;

            if (k < (int)adj[u].size()) {
                
                cout << adj[u][k] << endl;
            } else {
                
                cout << -1 << endl;
            }

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

int main(int argc, char** argv) {
    
    registerInteraction(argc, argv);
    atexit(on_exit);
    
    
    int t = inf.readInt();
    
    cout << t << endl;
    
    
    while(t--) {
        solve();
    }
    
    finish(_ok, "All cases passed");
    return 0;
}


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





void output(int n, vector<pair<int, int>> edges) {
    
    vector<int> p(n);
    iota(p.begin(), p.end(), 1);
    shuffle(p.begin(), p.end());

    
    vector<pair<int, int>> mapped_edges;
    mapped_edges.reserve(edges.size());
    for (auto e : edges) {
        int u = p[e.first - 1];
        int v = p[e.second - 1];
        if (u > v) swap(u, v);
        mapped_edges.push_back({u, v});
    }

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

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


void gen_random(int n, int m) {
    long long max_m = (long long)n * (n - 1) / 2;
    if (m > max_m) m = max_m;

    vector<pair<int, int>> edges;
    if (m > max_m / 2) {
        
        for (int i = 1; i <= n; ++i) {
            for (int j = i + 1; j <= n; ++j) {
                edges.push_back({i, j});
            }
        }
        shuffle(edges.begin(), edges.end());
        edges.resize(m);
    } else {
        
        set<pair<int, int>> edges_set;
        while ((int)edges_set.size() < m) {
            int u = rnd.next(1, n);
            int v = rnd.next(1, n);
            if (u == v) continue;
            if (u > v) swap(u, v);
            edges_set.insert({u, v});
        }
        for (auto e : edges_set) edges.push_back(e);
    }
    output(n, edges);
}


void gen_tree(int n) {
    if (n == 1) {
        output(n, {});
        return;
    }
    vector<pair<int, int>> edges;
    
    for (int i = 2; i <= n; ++i) {
        int p = rnd.next(1, i - 1);
        edges.push_back({p, i});
    }
    output(n, edges);
}


void gen_star(int n) {
    if (n == 1) {
        output(n, {});
        return;
    }
    vector<pair<int, int>> edges;
    for (int i = 2; i <= n; ++i) {
        edges.push_back({1, i});
    }
    output(n, edges);
}


void gen_forest(int n, int components) {
    if (n == 1) {
        output(n, {});
        return;
    }
    if (components >= n) {
        
        output(n, {});
        return;
    }

    
    set<int> cuts;
    while ((int)cuts.size() < components - 1) {
        cuts.insert(rnd.next(1, n - 1));
    }
    vector<int> sorted_cuts(cuts.begin(), cuts.end());
    vector<int> sizes;
    int prev = 0;
    for (int cut : sorted_cuts) {
        sizes.push_back(cut - prev);
        prev = cut;
    }
    sizes.push_back(n - prev);

    vector<pair<int, int>> edges;
    int offset = 1;
    for (int s : sizes) {
        
        if (s > 1) {
            
            for (int i = 1; i < s; ++i) {
                int u = offset + i;
                int p = offset + rnd.next(0, i - 1);
                edges.push_back({p, u});
            }
            
            int extra = rnd.next(0, min((int)(s * (s - 1) / 2 - (s - 1)), 2 * s));
            for (int k = 0; k < extra; ++k) {
                int u = rnd.next(offset, offset + s - 1);
                int v = rnd.next(offset, offset + s - 1);
                if (u != v) {
                    if (u > v) swap(u, v);
                    edges.push_back({u, v});
                }
            }
        }
        offset += s;
    }

    
    sort(edges.begin(), edges.end());
    edges.erase(unique(edges.begin(), edges.end()), edges.end());
    output(n, edges);
}


void gen_multi_stars(int n, int k) {
    if (n == 1) {
        output(n, {});
        return;
    }
    vector<pair<int, int>> edges;
    int remaining = n - k; 
    if (remaining < 0) remaining = 0; 
    
    int current_node = k + 1;
    for (int i = 1; i <= k; ++i) {
        if (remaining == 0) break;
        int count = (i == k) ? remaining : rnd.next(0, remaining);
        remaining -= count;
        for (int j = 0; j < count; ++j) {
            edges.push_back({i, current_node++});
        }
    }
    output(n, edges);
}

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

    
    int seed = atoi(argv[1]);

    
    if (seed == 1) { 
        output(1, {});
        return 0;
    }
    if (seed == 2) { 
        output(5, {{1,2}, {2,3}, {3,4}, {4,5}});
        return 0;
    }
    if (seed == 3) { 
        gen_star(6);
        return 0;
    }
    if (seed == 4) { 
        gen_random(5, 10);
        return 0;
    }
    if (seed == 5) { 
        output(6, {{1,2}, {2,3}, {1,3}, {4,5}, {5,6}, {4,6}});
        return 0;
    }

    
    int n;
    if (seed % 10 == 0) n = rnd.next(1, 20);           
    else if (seed % 10 == 1) n = rnd.next(900, 1000);  
    else n = rnd.next(50, 1000);                       

    
    int type = rnd.next(1, 6);
    
    
    if (seed > 100) { 
        type = rnd.next(1, 10);
        if (type > 6) type = 4; 
    }

    switch(type) {
        case 1: { 
            long long lim = (long long)n * (n - 1) / 2;
            int m = rnd.next(0, (int)min(lim, (long long)n * 2));
            gen_random(n, m);
            break;
        }
        case 2: { 
            long long lim = (long long)n * (n - 1) / 2;
            int low = min(lim, (long long)n * 3);
            int m = rnd.next(low, (int)lim);
            gen_random(n, m);
            break;
        }
        case 3: 
            gen_tree(n);
            break;
        case 4: 
            gen_forest(n, rnd.next(2, max(2, n / 10)));
            break;
        case 5: 
            gen_multi_stars(n, rnd.next(1, max(1, n / 5)));
            break;
        case 6: 
            gen_star(n);
            break;
        default:
            gen_random(n, n);
            break;
    }

    return 0;
}