Problem: cf1033_e
Difficulty: medium
Categories: graph, search
Time limit: 4000 ms, memory limit: 256 MB

Bob has a simple undirected connected graph (without self-loops and multiple edges). He wants to learn whether his graph is bipartite (that is, you can paint all vertices of the graph into two colors so that there is no edge connecting two vertices of the same color) or not. As he is not very good at programming, he asked Alice for help. He does not want to disclose his graph to Alice, but he agreed that Alice can ask him some questions about the graph.

The only question that Alice can ask is the following: she sends $s$ — a subset of vertices of the original graph. Bob answers with the number of edges that have both endpoints in $s$. Since he doesn't want Alice to learn too much about the graph, he allows her to ask no more than $20000$ questions. Furthermore, he suspects that Alice might introduce false messages to their communication channel, so when Alice finally tells him whether the graph is bipartite or not, she also needs to provide a proof — either the partitions themselves or a cycle of odd length.

Your task is to help Alice to construct the queries, find whether the graph is bipartite.

Input

The first line contains a single integer $n$ ($1 \leq n \leq 600$) — the number of vertices in Bob's graph.

Interaction

First, read an integer $n$ ($1\leq n\leq 600$) — the number of vertices in Bob's graph.

To make a query, print two lines. First of which should be in the format "? k" ($1 \leq k \leq n$), where $k$ is the size of the set to be queried. The second line should contain $k$ space separated distinct integers $s_1, s_2, \dots, s_k$ ($1 \leq s_i \leq n$) — the vertices of the queried set.

After each query read a single integer $m$ ($0 \leq m \leq \frac{n(n-1)}{2}$) — the number of edges between the vertices of the set $\{s_i\}$.

You are not allowed to ask more than $20000$ queries.

If $m = -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.

After printing a query 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.

When you know the answer, you need to print it.

The format of the answer depends on whether the graph is bipartite or not.

If the graph is bipartite, print two lines. The first should contain the letter "Y" (short for "YES") followed by a space, and then a single integer $s$ ($0 \leq s \leq n$) — the number of vertices in one of the partitions. Second line should contain $s$ integers $a_1, a_2, \dots, a_s$ — vertices belonging to the first partition. All $a_i$ must be distinct, and all edges in the main graph must have exactly one endpoint in the set $\{a_i\}$.

If the graph is not bipartite, print two lines. The first should contain the letter "N" (short for "NO") followed by a space, and then a single integer $l$ ($3 \leq l \leq n$) — the length of one simple cycle of odd length. Second line should contain $l$ integers $c_1, c_2, \dots, c_l$ — the vertices along the cycle. It must hold that for all $1 \leq i \leq l$, there is an edge $\{c_i, c_{(i \mod l)+1}\}$ in the main graph, and all $c_i$ are distinct.

If there are multiple possible answers, you may print any of them.

Examples

Input

```
4  
4  
0  
1  
1  
1  
0
```

Output

```
? 4   
1 2 3 4  
? 2  
1 2  
? 2  
1 3  
? 2  
1 4  
? 2  
2 4  
? 2  
3 4  
Y 2  
1 2
```

Input

```
4  
4  
3
```

Output

```
? 4  
1 4 2 3  
? 3  
1 2 4  
N 3  
2 1 4
```

Note

In the first case, Alice learns that there are $4$ edges in the whole graph. Over the course of the next three queries, she learns that vertex $1$ has two neighbors: $3$ and $4$. She then learns that while vertex $2$ is adjacent to $4$, the vertex $3$ isn't adjacent to $4$. There is only one option for the remaining edge, and that is $(2, 3)$. This means that the graph is a cycle on four vertices, with $(1, 2)$ being one partition and $(3, 4)$ being the second. Here, it would be also valid to output "3 4" on the second line.

In the second case, we also have a graph on four vertices and four edges. In the second query, Alice learns that there are three edges among vertices $(1, 2, 4)$. The only way this could possibly happen is that those form a triangle. As the triangle is not bipartite, Alice can report it as a proof. Notice that she does not learn where the fourth edge is, but she is able to answer Bob correctly anyway.

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 void log_metrics() {
    try {
        tout << "queries=" << queries << "\n";
        tout << "query_limit=" << query_limit << "\n";
        tout.flush();
    } catch (...) {
        
    }
}

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

static bool readToken(string& s) {
    return (cin >> s) ? true : false;
}

static bool readLL(long long& x) {
    return (cin >> x) ? true : false;
}

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

    const int MAXN = 605;

    int n = inf.readInt(1, 600, "n");
    int m = inf.readInt(0, n * (n - 1) / 2, "m");

    vector<bitset<MAXN>> adj(n + 1);
    vector<pair<int,int>> edges;
    edges.reserve(m);

    for (int i = 0; i < m; i++) {
        int u = inf.readInt(1, n, "u");
        int v = inf.readInt(1, n, "v");
        if (u == v) finish(_fail, "Hidden input has self-loop");
        if (u > v) swap(u, v);
        if (adj[u].test(v)) finish(_fail, "Hidden input has multiple edge");
        adj[u].set(v);
        adj[v].set(u);
        edges.push_back({u, v});
    }

    query_limit = 20000;
    log_metrics(); 

    cout << n << "\n" << flush;

    const long long hard_cap = max(200000LL, 10LL * query_limit);

    while (true) {
        string cmd;
        if (!readToken(cmd)) {
            finish(_pe, "Unexpected EOF from contestant");
        }

        if (cmd == "?") {
            if (++queries > hard_cap) {
                finish(_pe, "Hard cap exceeded");
            }

            long long kll;
            if (!readLL(kll)) finish(_pe, "Missing k after '?'");
            if (kll < 1 || kll > n) finish(_pe, "Invalid k in query");
            int k = (int)kll;

            vector<int> verts;
            verts.reserve(k);
            bitset<MAXN> mask;
            for (int i = 0; i < k; i++) {
                long long vll;
                if (!readLL(vll)) finish(_pe, "Not enough vertices in query");
                if (vll < 1 || vll > n) finish(_pe, "Vertex out of range in query");
                int v = (int)vll;
                if (mask.test(v)) finish(_pe, "Duplicate vertex in query");
                mask.set(v);
                verts.push_back(v);
            }

            long long cnt2 = 0;
            for (int v : verts) {
                cnt2 += (adj[v] & mask).count();
            }
            long long induced_edges = cnt2 / 2;

            cout << induced_edges << "\n" << flush;
            continue;
        }

        if (cmd == "Y") {
            long long sll;
            if (!readLL(sll)) finish(_pe, "Missing s after 'Y'");
            if (sll < 0 || sll > n) finish(_pe, "Invalid s after 'Y'");
            int s = (int)sll;

            vector<char> inA(n + 1, 0);
            for (int i = 0; i < s; i++) {
                long long vll;
                if (!readLL(vll)) finish(_pe, "Not enough vertices for partition");
                if (vll < 1 || vll > n) finish(_pe, "Partition vertex out of range");
                int v = (int)vll;
                if (inA[v]) finish(_pe, "Duplicate vertex in partition");
                inA[v] = 1;
            }

            for (auto [u, v] : edges) {
                if (inA[u] == inA[v]) {
                    finish(_wa, "Provided partition is not a valid bipartition");
                }
            }

            finish(_ok, "Correct: valid bipartition provided");
        }

        if (cmd == "N") {
            long long lll;
            if (!readLL(lll)) finish(_pe, "Missing l after 'N'");
            if (lll < 3 || lll > n) finish(_pe, "Invalid l after 'N'");
            int l = (int)lll;
            if ((l % 2) == 0) finish(_wa, "Provided cycle length is not odd");

            vector<int> cyc;
            cyc.reserve(l);
            vector<char> used(n + 1, 0);

            for (int i = 0; i < l; i++) {
                long long vll;
                if (!readLL(vll)) finish(_pe, "Not enough vertices for cycle");
                if (vll < 1 || vll > n) finish(_pe, "Cycle vertex out of range");
                int v = (int)vll;
                if (used[v]) finish(_wa, "Cycle is not simple (repeated vertex)");
                used[v] = 1;
                cyc.push_back(v);
            }

            for (int i = 0; i < l; i++) {
                int a = cyc[i];
                int b = cyc[(i + 1) % l];
                if (a == b) finish(_wa, "Cycle has repeated adjacent vertices");
                if (!adj[a].test(b)) {
                    finish(_wa, "Provided cycle edge does not exist in hidden graph");
                }
            }

            finish(_ok, "Correct: valid odd cycle provided");
        }

        finish(_pe, "Unknown command token");
    }
}


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 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());
}

static constexpr int MAXN = 600;
static constexpr int BITS = MAXN + 1;          
static constexpr int WORDS = (BITS + 63) / 64; 

struct Bitset {
    array<uint64_t, WORDS> w{};

    inline void resetAll() {
        for (auto& x : w) x = 0;
    }

    inline void setBit(int idx) {
        w[(unsigned)idx >> 6] |= (1ULL << (idx & 63));
    }
    inline void resetBit(int idx) {
        w[(unsigned)idx >> 6] &= ~(1ULL << (idx & 63));
    }
    inline bool testBit(int idx) const {
        return (w[(unsigned)idx >> 6] >> (idx & 63)) & 1ULL;
    }

    inline long long countAnd(const Bitset& other) const {
        long long res = 0;
        for (int i = 0; i < WORDS; i++) res += __builtin_popcountll(w[i] & other.w[i]);
        return res;
    }

    inline void andInto(const Bitset& other) {
        for (int i = 0; i < WORDS; i++) w[i] &= other.w[i];
    }
};

static inline bool readTokenSafe(string& t) {
    return (cin >> t) ? true : false;
}

static inline bool readIntSafe(long long& x) {
    return (cin >> x) ? true : false;
}

static inline void replyAndFlush(long long x) {
    cout << x << endl;
    cout.flush();
}

static inline void replyErrorAndFlush() {
    cout << -1 << endl;
    cout.flush();
}

static inline int clampInt(long long x, int lo, int hi) {
    if (x < lo) return lo;
    if (x > hi) return hi;
    return (int)x;
}

struct FixedGraphJudge {
    int n = 0;
    long long m = 0;
    vector<Bitset> adj; 

    bool hasEdge(int u, int v) const {
        if (u < 1 || v < 1 || u > n || v > n || u == v) return false;
        return adj[u].testBit(v);
    }

    long long answerQuery(const vector<int>& s) const {
        Bitset subset;
        subset.resetAll();
        for (int v : s) subset.setBit(v);
        long long sum = 0;
        for (int v : s) sum += adj[v].countAnd(subset);
        return sum / 2;
    }
};

struct AdaptiveBipartiteJudge {
    int n = 0;
    long long m_total = 0;

    vector<int> side; 
    vector<Bitset> ones;    
    vector<Bitset> unknown; 

    long long fixedOneTotal = 0;   
    long long undecidedGlobal = 0; 

    bool hasEdge(int u, int v) const {
        if (u < 1 || v < 1 || u > n || v > n || u == v) return false;
        return ones[u].testBit(v);
    }

    long long answerQueryAndFixAllInside(const vector<int>& s) {
        Bitset rightSubset;
        rightSubset.resetAll();

        vector<int> leftList;
        leftList.reserve(s.size());

        for (int v : s) {
            if (side[v] == 1) rightSubset.setBit(v);
            else leftList.push_back(v);
        }
        sort(leftList.begin(), leftList.end());

        long long fixed1 = 0;
        long long unk = 0;

        for (int u : leftList) {
            fixed1 += ones[u].countAnd(rightSubset);
            unk += unknown[u].countAnd(rightSubset);
        }

        
        long long afterUndec = undecidedGlobal - unk;
        long long remBefore = m_total - fixedOneTotal;

        long long x_min = max(0LL, remBefore - afterUndec);
        long long x_max = min(unk, remBefore);

        if (x_min > x_max) {
            finish(_pe, "internal: infeasible range for adaptive response");
        }

        
        
        auto score = [&](long long x) -> long long {
            long long remAfter = remBefore - x;
            
            return llabs(2 * remAfter - afterUndec);
        };

        long long targetX = remBefore - (afterUndec / 2);
        long long bestX = x_min;
        long long bestScore = score(bestX);

        auto consider = [&](long long x) {
            if (x < x_min || x > x_max) return;
            long long sc = score(x);
            if (sc < bestScore || (sc == bestScore && x < bestX)) {
                bestScore = sc;
                bestX = x;
            }
        };

        consider(targetX);
        consider(targetX - 1);
        consider(targetX + 1);
        consider(x_max);

        long long needOnes = bestX;
        
        for (int u : leftList) {
            for (int wi = 0; wi < WORDS; wi++) {
                uint64_t x = unknown[u].w[wi] & rightSubset.w[wi];
                while (x) {
                    int b = __builtin_ctzll(x);
                    int v = wi * 64 + b;
                    x &= (x - 1);

                    if (v < 1 || v > n) continue; 
                    
                    unknown[u].resetBit(v);
                    unknown[v].resetBit(u);
                    if (needOnes > 0) {
                        ones[u].setBit(v);
                        ones[v].setBit(u);
                        needOnes--;
                    }
                }
            }
        }

        if (needOnes != 0) {
            finish(_pe, "internal: failed to assign required number of edges in subset");
        }

        fixedOneTotal += bestX;
        undecidedGlobal = afterUndec;

        return fixed1 + bestX;
    }

    void finalizeGraph() {
        long long need = m_total - fixedOneTotal;
        if (need < 0 || need > undecidedGlobal) {
            finish(_pe, "internal: cannot finalize to required total edge count");
        }

        
        for (int u = 1; u <= n && need > 0; u++) {
            if (side[u] != 0) continue;
            for (int wi = 0; wi < WORDS && need > 0; wi++) {
                uint64_t x = unknown[u].w[wi];
                while (x && need > 0) {
                    int b = __builtin_ctzll(x);
                    int v = wi * 64 + b;
                    x &= (x - 1);

                    if (v < 1 || v > n) continue;
                    
                    unknown[u].resetBit(v);
                    unknown[v].resetBit(u);
                    ones[u].setBit(v);
                    ones[v].setBit(u);
                    need--;
                    fixedOneTotal++;
                }
            }
        }

        
        for (int u = 1; u <= n; u++) unknown[u].resetAll();

        if (need != 0) {
            finish(_pe, "internal: failed to reach required total edge count");
        }
        undecidedGlobal = 0;
    }
};

static void validateDistinctVerticesOrPE(const vector<int>& s, int n) {
    vector<unsigned char> seen(n + 1, 0);
    for (int v : s) {
        if (v < 1 || v > n) finish(_pe, "vertex out of range");
        if (seen[v]) finish(_pe, "duplicate vertex in set");
        seen[v] = 1;
    }
}

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

    int n = inf.readInt(1, 600, "n");
    long long m = inf.readLong(0, 1LL * n * (n - 1) / 2, "m");

    vector<pair<int, int>> edges;
    while (!inf.seekEof()) {
        int u = inf.readInt(1, n, "u");
        int v = inf.readInt(1, n, "v");
        edges.push_back({u, v});
    }

    query_limit = 20000;
    log_metrics(); 

    const long long hard_cap = max(200000LL, 10LL * query_limit);

    bool fixedGraphMode = ((long long)edges.size() == m);

    FixedGraphJudge fixed;
    AdaptiveBipartiteJudge adp;

    if (fixedGraphMode) {
        fixed.n = n;
        fixed.m = m;
        fixed.adj.assign(n + 1, Bitset{});
        for (int i = 1; i <= n; i++) fixed.adj[i].resetAll();

        vector<vector<unsigned char>> has(n + 1, vector<unsigned char>(n + 1, 0));
        for (auto [u, v] : edges) {
            if (u == v) finish(_pe, "hidden input has self-loop");
            if (has[u][v] || has[v][u]) finish(_pe, "hidden input has multiple edges");
            has[u][v] = has[v][u] = 1;
            fixed.adj[u].setBit(v);
            fixed.adj[v].setBit(u);
        }
    } else {
        
        if (!((int)edges.size() == max(0, n - 1))) {
            finish(_pe, "invalid hidden input format (expected fixed graph or adaptive schema)");
        }

        adp.n = n;
        adp.m_total = m;
        adp.side.assign(n + 1, -1);
        adp.ones.assign(n + 1, Bitset{});
        adp.unknown.assign(n + 1, Bitset{});
        for (int i = 1; i <= n; i++) {
            adp.ones[i].resetAll();
            adp.unknown[i].resetAll();
        }

        vector<vector<int>> treeAdj(n + 1);
        vector<vector<unsigned char>> mand(n + 1, vector<unsigned char>(n + 1, 0));

        for (auto [u, v] : edges) {
            if (u == v) finish(_pe, "hidden input has self-loop in mandatory edges");
            if (mand[u][v] || mand[v][u]) finish(_pe, "hidden input has duplicate mandatory edge");
            mand[u][v] = mand[v][u] = 1;
            treeAdj[u].push_back(v);
            treeAdj[v].push_back(u);
        }

        
        if (n >= 1) {
            queue<int> q;
            adp.side[1] = 0;
            q.push(1);
            while (!q.empty()) {
                int u = q.front();
                q.pop();
                for (int v : treeAdj[u]) {
                    if (adp.side[v] == -1) {
                        adp.side[v] = adp.side[u] ^ 1;
                        q.push(v);
                    } else if (adp.side[v] == adp.side[u]) {
                        finish(_pe, "hidden mandatory edges are not bipartite");
                    }
                }
            }
            for (int i = 1; i <= n; i++) {
                if (adp.side[i] == -1) finish(_pe, "hidden mandatory edges are disconnected");
            }
        }

        
        for (auto [u, v] : edges) {
            adp.ones[u].setBit(v);
            adp.ones[v].setBit(u);
        }
        adp.fixedOneTotal = (n <= 1) ? 0 : (long long)edges.size();

        long long leftCnt = 0, rightCnt = 0;
        for (int i = 1; i <= n; i++) {
            if (adp.side[i] == 0) leftCnt++;
            else rightCnt++;
        }
        long long totalCross = leftCnt * rightCnt;
        if (adp.m_total < (long long)edges.size() || adp.m_total > totalCross) {
            finish(_pe, "adaptive schema impossible: m outside feasible bipartite range");
        }

        for (int u = 1; u <= n; u++) {
            for (int v = 1; v <= n; v++) {
                if (u == v) continue;
                if (adp.side[u] == adp.side[v]) continue; 
                if (mand[u][v]) continue;                 
                
                adp.unknown[u].setBit(v);
            }
        }
        
        for (int u = 1; u <= n; u++) {
            for (int wi = 0; wi < WORDS; wi++) {
                uint64_t x = adp.unknown[u].w[wi];
                while (x) {
                    int b = __builtin_ctzll(x);
                    int v = wi * 64 + b;
                    x &= (x - 1);
                    if (v < 1 || v > n) continue;
                    adp.unknown[v].setBit(u);
                }
            }
        }

        
        long long unk = 0;
        for (int u = 1; u <= n; u++) {
            if (adp.side[u] != 0) continue;
            unk += adp.unknown[u].countAnd(Bitset{});
            
            long long cnt = 0;
            for (int wi = 0; wi < WORDS; wi++) cnt += __builtin_popcountll(adp.unknown[u].w[wi]);
            unk += cnt;
        }
        
        unk = 0;
        for (int u = 1; u <= n; u++) {
            if (adp.side[u] != 0) continue;
            long long cnt = 0;
            for (int wi = 0; wi < WORDS; wi++) cnt += __builtin_popcountll(adp.unknown[u].w[wi]);
            unk += cnt;
        }
        adp.undecidedGlobal = unk;
        
        if (adp.fixedOneTotal + adp.undecidedGlobal != totalCross) {
            finish(_pe, "internal: cross-edge accounting mismatch");
        }
    }

    
    cout << n << endl;
    cout.flush();

    for (;;) {
        string t;
        if (!readTokenSafe(t)) {
            finish(_pe, "unexpected EOF from contestant");
        }

        if (t == "?") {
            long long kll;
            if (!readIntSafe(kll)) {
                replyErrorAndFlush();
                finish(_pe, "malformed query: missing k");
            }
            if (kll < 1 || kll > n) {
                replyErrorAndFlush();
                finish(_pe, "malformed query: k out of range");
            }
            int k = (int)kll;

            vector<int> s;
            s.reserve(k);
            for (int i = 0; i < k; i++) {
                long long vll;
                if (!readIntSafe(vll)) {
                    replyErrorAndFlush();
                    finish(_pe, "malformed query: missing vertex");
                }
                if (vll < 1 || vll > n) {
                    replyErrorAndFlush();
                    finish(_pe, "malformed query: vertex out of range");
                }
                s.push_back((int)vll);
            }
            
            {
                vector<unsigned char> seen(n + 1, 0);
                for (int v : s) {
                    if (seen[v]) {
                        replyErrorAndFlush();
                        finish(_pe, "malformed query: duplicate vertex");
                    }
                    seen[v] = 1;
                }
            }

            queries++;
            if (queries > hard_cap) {
                replyErrorAndFlush();
                finish(_pe, "too many queries (hard cap)");
            }

            long long ans = 0;
            if (fixedGraphMode) {
                ans = fixed.answerQuery(s);
            } else {
                ans = adp.answerQueryAndFixAllInside(s);
            }

            if (ans < 0 || ans > 1LL * n * (n - 1) / 2) {
                replyErrorAndFlush();
                finish(_pe, "internal: computed invalid answer");
            }

            replyAndFlush(ans);
            continue;
        }

        
        if (t == "Y") {
            long long sll;
            if (!readIntSafe(sll)) finish(_pe, "malformed final answer: missing s");
            if (sll < 0 || sll > n) finish(_pe, "malformed final answer: s out of range");
            int ssz = (int)sll;

            vector<int> part;
            part.reserve(ssz);
            for (int i = 0; i < ssz; i++) {
                long long vll;
                if (!readIntSafe(vll)) finish(_pe, "malformed final answer: missing vertex in partition");
                if (vll < 1 || vll > n) finish(_pe, "malformed final answer: vertex out of range");
                part.push_back((int)vll);
            }
            validateDistinctVerticesOrPE(part, n);

            vector<unsigned char> inA(n + 1, 0);
            for (int v : part) inA[v] = 1;

            if (!fixedGraphMode) adp.finalizeGraph();

            auto checkEdgeCross = [&](int u, int v) {
                if (inA[u] == inA[v]) {
                    finish(_wa, "claimed bipartition has same-side edge");
                }
            };

            if (fixedGraphMode) {
                
                for (int u = 1; u <= n; u++) {
                    for (int wi = 0; wi < WORDS; wi++) {
                        uint64_t x = fixed.adj[u].w[wi];
                        while (x) {
                            int b = __builtin_ctzll(x);
                            int v = wi * 64 + b;
                            x &= (x - 1);
                            if (v < 1 || v > n) continue;
                            if (v <= u) continue;
                            checkEdgeCross(u, v);
                        }
                    }
                }
            } else {
                
                for (int u = 1; u <= n; u++) {
                    if (adp.side[u] != 0) continue;
                    for (int wi = 0; wi < WORDS; wi++) {
                        uint64_t x = adp.ones[u].w[wi];
                        while (x) {
                            int b = __builtin_ctzll(x);
                            int v = wi * 64 + b;
                            x &= (x - 1);
                            if (v < 1 || v > n) continue;
                            checkEdgeCross(u, v);
                        }
                    }
                }
            }

            finish(_ok, "correct: valid bipartition");
        }

        if (t == "N") {
            long long lll;
            if (!readIntSafe(lll)) finish(_pe, "malformed final answer: missing l");
            if (lll < 3 || lll > n) finish(_pe, "malformed final answer: l out of range");
            int L = (int)lll;
            if ((L & 1) == 0) finish(_pe, "malformed final answer: l must be odd");

            vector<int> cyc;
            cyc.reserve(L);
            for (int i = 0; i < L; i++) {
                long long vll;
                if (!readIntSafe(vll)) finish(_pe, "malformed final answer: missing cycle vertex");
                if (vll < 1 || vll > n) finish(_pe, "malformed final answer: cycle vertex out of range");
                cyc.push_back((int)vll);
            }
            validateDistinctVerticesOrPE(cyc, n);

            if (!fixedGraphMode) adp.finalizeGraph();

            auto hasE = [&](int u, int v) -> bool {
                if (fixedGraphMode) return fixed.hasEdge(u, v);
                return adp.hasEdge(u, v);
            };

            for (int i = 0; i < L; i++) {
                int u = cyc[i];
                int v = cyc[(i + 1) % L];
                if (!hasE(u, v)) {
                    finish(_wa, "claimed odd cycle uses a non-edge");
                }
            }

            finish(_ok, "correct: valid odd cycle");
        }

        finish(_pe, "unexpected token from contestant");
    }
}


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

static long long parseSeed(int argc, char** argv) {
    if (argc < 2) return 1;
    char* endp = nullptr;
    long long s = strtoll(argv[1], &endp, 10);
    if (endp == argv[1]) return 1;
    return s;
}

static void shuffleVec(vector<int>& v, int l, int r) {
    for (int i = r; i > l; --i) {
        int j = rnd.next(l, i);
        swap(v[i], v[j]);
    }
}

static void shufflePairs(vector<pair<int,int>>& v) {
    for (int i = (int)v.size() - 1; i >= 1; --i) {
        int j = rnd.next(0, i);
        swap(v[i], v[j]);
    }
}

struct GraphBuilder {
    int n;
    vector<vector<unsigned char>> has;
    vector<pair<int,int>> edges;

    explicit GraphBuilder(int n_) : n(n_), has(n_ + 1, vector<unsigned char>(n_ + 1, 0)) {}

    bool addEdge(int u, int v) {
        if (u == v) return false;
        if (u > v) swap(u, v);
        if (has[u][v]) return false;
        has[u][v] = 1;
        edges.push_back({u, v});
        return true;
    }

    void applyPermutation(const vector<int>& perm) {
        vector<pair<int,int>> newEdges;
        newEdges.reserve(edges.size());
        for (auto [u, v] : edges) {
            int nu = perm[u], nv = perm[v];
            if (nu > nv) swap(nu, nv);
            newEdges.push_back({nu, nv});
        }
        sort(newEdges.begin(), newEdges.end());
        newEdges.erase(unique(newEdges.begin(), newEdges.end()), newEdges.end());

        has.assign(n + 1, vector<unsigned char>(n + 1, 0));
        edges.clear();
        edges.reserve(newEdges.size());
        for (auto [u, v] : newEdges) addEdge(u, v);
    }
};

static vector<int> makePermutation(int n) {
    vector<int> perm(n + 1);
    for (int i = 1; i <= n; i++) perm[i] = i;
    for (int i = n; i >= 2; --i) {
        int j = rnd.next(1, i);
        swap(perm[i], perm[j]);
    }
    return perm;
}

static GraphBuilder makeSmallCase(long long seed) {
    if (seed == 1) {
        GraphBuilder g(1);
        return g;
    }
    if (seed == 2) {
        GraphBuilder g(2);
        g.addEdge(1, 2);
        return g;
    }
    GraphBuilder g(3);
    g.addEdge(1, 2);
    g.addEdge(2, 3);
    g.addEdge(1, 3);
    return g;
}

static GraphBuilder makeBipartiteDense(int n, int targetM) {
    int a = n / 2;
    int b = n - a;

    vector<int> A(a), B(b);
    for (int i = 0; i < a; i++) A[i] = 1 + i;
    for (int i = 0; i < b; i++) B[i] = 1 + a + i;

    GraphBuilder g(n);

    vector<int> seq;
    seq.reserve(n);
    int i = 0, j = 0;
    while (i < a || j < b) {
        if (i < a) seq.push_back(A[i++]);
        if (j < b) seq.push_back(B[j++]);
    }
    for (int k = 0; k + 1 < n; k++) g.addEdge(seq[k], seq[k + 1]);

    int minNeed = (int)g.edges.size();
    int maxBip = a * b;
    targetM = max(targetM, minNeed);
    targetM = min(targetM, maxBip);

    vector<pair<int,int>> cand;
    cand.reserve((size_t)maxBip);
    for (int u : A) for (int v : B) cand.push_back({u, v});
    shufflePairs(cand);

    for (auto [u, v] : cand) {
        if ((int)g.edges.size() >= targetM) break;
        g.addEdge(u, v);
    }

    return g;
}

static GraphBuilder makeNonBipLongOddCycle(int n) {
    GraphBuilder g(n);
    if (n <= 2) {
        if (n == 2) g.addEdge(1, 2);
        return g;
    }

    int L = (n % 2 == 1) ? n : (n - 1);
    if (L < 3) L = 3;

    for (int i = 1; i < L; i++) g.addEdge(i, i + 1);
    g.addEdge(1, L);

    for (int v = L + 1; v <= n; v++) {
        int attach = rnd.next(1, L);
        g.addEdge(attach, v);
    }

    vector<int> perm = makePermutation(n);
    g.applyPermutation(perm);
    return g;
}

static GraphBuilder makeBipartiteSparseTree(int n) {
    GraphBuilder g(n);
    if (n <= 1) return g;
    vector<int> perm = makePermutation(n);
    for (int i = 2; i <= n; i++) {
        int parent = rnd.next(1, i - 1);
        g.addEdge(perm[parent], perm[i]);
    }
    return g;
}

static GraphBuilder makeNonBipDenseTriangleFreeOdd5(int n) {
    int a = n / 2;
    int b = n - a;
    if (a < 3 || b < 2) return makeNonBipLongOddCycle(n);

    vector<int> A(a), B(b);
    for (int i = 0; i < a; i++) A[i] = 1 + i;
    for (int i = 0; i < b; i++) B[i] = 1 + a + i;

    int u = A[0];
    int v = A[1];
    int w = A[2];

    vector<int> B1, B2;
    for (int i = 0; i < b; i++) {
        if (i < b / 2) B1.push_back(B[i]);
        else B2.push_back(B[i]);
    }
    if (B1.empty() || B2.empty()) return makeNonBipLongOddCycle(n);

    GraphBuilder g(n);

    for (int x : B1) g.addEdge(u, x);
    for (int x : B2) g.addEdge(v, x);

    for (int x : B) g.addEdge(w, x);
    for (int i = 3; i < a; i++) for (int x : B) g.addEdge(A[i], x);

    g.addEdge(u, v);

    vector<int> perm = makePermutation(n);
    g.applyPermutation(perm);
    return g;
}

static void outputNonInstance(const GraphBuilder& g) {
    cout << g.n << "\n";
    cout << (int)g.edges.size() << "\n";
    for (auto [u, v] : g.edges) cout << u << " " << v << "\n";
}

static void outputAdaptiveSchema(int n, int m, const vector<pair<int,int>>& treeEdges) {
    cout << n << "\n";
    cout << m << "\n";
    for (auto [u, v] : treeEdges) cout << u << " " << v << "\n";
}

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

    string mode = opt<string>("mode", "non");
    long long seed = parseSeed(argc, argv);

    int nOpt = opt<int>("n", 600);
    int n = nOpt;
    n = max(1, min(600, n));

    if (seed >= 1 && seed <= 3) {
        if (mode == "non") {
            GraphBuilder g = makeSmallCase(seed);
            outputNonInstance(g);
            return 0;
        }
        if (mode == "adp") {
            int nSmall = (seed == 1 ? 1 : (seed == 2 ? 2 : 3));
            int mSmall = (seed == 1 ? 0 : (seed == 2 ? 1 : 3));
            vector<pair<int,int>> tree;
            for (int i = 1; i < nSmall; i++) tree.push_back({i, i + 1});
            outputAdaptiveSchema(nSmall, mSmall, tree);
            return 0;
        }
        quitf(_fail, "Unknown mode: %s", mode.c_str());
    }

    if (mode == "non") {
        int pattern = (int)(llabs(seed) % 4);
        GraphBuilder g(1);
        if (pattern == 0) {
            int a = n / 2;
            int b = n - a;
            int maxBip = a * b;
            int defTarget = maxBip - rnd.next(0, max(1, maxBip / 8));
            int targetM = opt<int>("m", defTarget);
            g = makeBipartiteDense(n, targetM);
        } else if (pattern == 1) {
            g = makeNonBipLongOddCycle(n);
        } else if (pattern == 2) {
            g = makeBipartiteSparseTree(n);
        } else {
            g = makeNonBipDenseTriangleFreeOdd5(n);
        }
        outputNonInstance(g);
        return 0;
    }

    if (mode == "adp") {
        int a = n / 2;
        int b = n - a;
        int maxBip = a * b;
        int pattern = (int)(llabs(seed) % 4);

        int mDefault;
        if (pattern == 0 || pattern == 3) {
            mDefault = maxBip - rnd.next(0, n);
        } else {
            mDefault = max(n - 1, 2 * n + rnd.next(0, n));
            mDefault = min(mDefault, maxBip);
        }
        int m = opt<int>("m", mDefault);
        m = max(n - 1, m);

        vector<pair<int,int>> tree;
        tree.reserve(max(0, n - 1));
        vector<int> perm = makePermutation(n);
        for (int i = 1; i < n; i++) tree.push_back({perm[i], perm[i + 1]});

        outputAdaptiveSchema(n, m, tree);
        return 0;
    }

    quitf(_fail, "Unknown mode: %s", mode.c_str());
}