Problem: abc398_e
Difficulty: easy
Categories: graph, game
Time limit: 2000 ms, memory limit: 1024 MB

### Problem Statement

This problem is an **interactive problem** (in which your program and the judge system communicate via input and output).

You are given a tree $G$ with $N$ vertices numbered $1$ to $N$. The $i$-th edge connects vertices $U_i$ and $V_i$.

You will play a game with Takahashi using this tree $G$. First, you decide who is first and who is second. Then, starting from the first player, take turns performing the following operation:

* Choose a pair of integers $(i,j)$ with $1 \leq i < j \leq N$ that satisfies both of the following conditions, then add an edge connecting vertices $i$ and $j$ to $G$.
  + $G$ does not already have an edge connecting vertices $i$ and $j$.
  + Adding an edge connecting vertices $i$ and $j$ does not create an odd cycle.

A player who cannot perform this operation loses, and the other player wins. Play this game against Takahashi and win.

What is an odd cycle?

A sequence of vertices $(v_0,v_1,\ldots,v_k)$ of $G$ is called an odd cycle if and only if all of the following conditions are satisfied:

* $k$ is odd.
* $v_0=v_k$.
* For every $1\leq i \leq k$, there is an edge connecting $v_{i-1}$ and $v_{i}$.

### Constraints

* $2 \leq N \leq 100$
* $1 \leq U_i < V_i \leq N$
* The given graph is a tree.
* All input values are integers.

### Interaction

This is an interactive problem (in which your program and the judge system communicate via input and output).

First, read $N$ and the edges of $G$ from Standard Input, given in the following format:

```
$N$
$U_1$ $V_1$
$U_2$ $V_2$
$\vdots$
$U_{N-1}$ $V_{N-1}$
```

Then, decide whether you go first or second. If you choose first, print `First`; if second, print `Second`.

Then, the game begins.

On your turn, output the chosen pair $(i,j)$ by printing two integers $i$ and $j$ in this order, separated by a space:

```
$i$ $j$
```

On Takahashi's turn, two integers $i,j$ will be given in order, separated by a space, via Standard Input:

```
$i$ $j$
```

If $(i,j)=(-1,-1)$, it means he can no longer make a move and you win. Immediately terminate your program in this case.  
Otherwise, $(i,j)$ is the pair of integers he has chosen.

### Notes

* **After each output, be sure to print a newline and flush Standard Output. Otherwise, you may get TLE.**
* **If you produce output in an incorrect format or your program ends prematurely, the judge result is indeterminate.**
* Once the game finishes, terminate your program immediately. Otherwise, the judge result is indeterminate.

### Sample Interaction

| Input | Output | Explanation |
| --- | --- | --- |
| `4 1 2 2 3 3 4` |  | First, you receive $N$ and the edges of $G$. |
|  | `First` | You choose to go first. |
|  | `1 4` | You add an edge between vertices $1$ and $4$. |
| `-1 -1` |  | Takahashi can no longer move, so you win. The judge result will be AC. |

Non-adaptive interactor (C++):
#include "testlib.h"

#include <bits/stdc++.h>
#include <csignal>

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 string to_lower_ascii(string s) {
    for (char& c : s) c = (char)tolower((unsigned char)c);
    return s;
}

int main(int argc, char** argv) {
    registerInteraction(argc, argv);
    atexit(log_metrics);
#ifdef SIGPIPE
    signal(SIGPIPE, SIG_IGN);
#endif

    const int N = inf.readInt();
    if (N < 2 || N > 100) finish(_fail, "invalid N in hidden input");

    vector<pair<int, int>> edges;
    edges.reserve(max(0, N - 1));
    vector<vector<int>> adj(N + 1);
    vector<vector<unsigned char>> has_edge(N + 1, vector<unsigned char>(N + 1, 0));
    for (int i = 0; i < N - 1; i++) {
        int u = inf.readInt();
        int v = inf.readInt();
        if (u < 1 || u > N || v < 1 || v > N || u == v) finish(_fail, "invalid edge in hidden input");
        if (u > v) swap(u, v);
        if (has_edge[u][v]) finish(_fail, "duplicate edge in hidden input");
        has_edge[u][v] = has_edge[v][u] = 1;
        edges.push_back({u, v});
        adj[u].push_back(v);
        adj[v].push_back(u);
    }

    
    cout << N << "\n";
    for (auto [u, v] : edges) {
        cout << u << " " << v << "\n";
    }
    cout.flush();

    
    vector<int> color(N + 1, -1);
    queue<int> q;
    color[1] = 0;
    q.push(1);
    while (!q.empty()) {
        int x = q.front();
        q.pop();
        for (int y : adj[x]) {
            if (color[y] == -1) {
                color[y] = color[x] ^ 1;
                q.push(y);
            } else if (color[y] == color[x]) {
                finish(_fail, "hidden input graph is not bipartite");
            }
        }
    }
    for (int i = 1; i <= N; i++) {
        if (color[i] == -1) finish(_fail, "hidden input graph is not connected");
    }

    set<pair<int, int>> remaining;
    for (int i = 1; i <= N; i++) {
        for (int j = i + 1; j <= N; j++) {
            if (color[i] == color[j]) continue;
            if (has_edge[i][j]) continue;
            remaining.insert({i, j});
        }
    }
    query_limit = (long long)remaining.size();
    log_metrics();

    string role;
    if (!(cin >> role)) finish(_pe, "EOF (expected First/Second)");
    role = to_lower_ascii(role);

    bool contestant_first = false;
    if (role == "first") {
        contestant_first = true;
    } else if (role == "second") {
        contestant_first = false;
    } else {
        finish(_pe, "Invalid role (expected First/Second)");
    }

    bool contestant_turn = contestant_first;
    while (true) {
        if (contestant_turn) {
            int x, y;
            if (!(cin >> x >> y)) finish(_pe, "EOF (expected move)");

            if (x == -1 && y == -1) {
                if (remaining.empty()) finish(_wa, "Contestant cannot move (loses)");
                finish(_wa, "Contestant resigned with moves remaining");
            }

            if (x < 1 || x > N || y < 1 || y > N || x >= y) finish(_pe, "Invalid move format");
            if (has_edge[x][y]) finish(_wa, "Edge already exists");
            if (color[x] == color[y]) finish(_wa, "Move creates an odd cycle");

            auto it = remaining.find({x, y});
            if (it == remaining.end()) finish(_wa, "Illegal move");
            remaining.erase(it);
            has_edge[x][y] = has_edge[y][x] = 1;
            queries++;
            if (queries % 64 == 0) log_metrics();

            contestant_turn = false;
            continue;
        }

        
        if (remaining.empty()) {
            cout << -1 << " " << -1 << endl;  
            finish(_ok, "Contestant wins");
        }

        auto mv = *remaining.begin();
        remaining.erase(remaining.begin());
        has_edge[mv.first][mv.second] = has_edge[mv.second][mv.first] = 1;
        cout << mv.first << " " << mv.second << endl;
        if (!cout) finish(_pe, "Broken pipe while writing move");
        contestant_turn = true;
    }
}


Adaptive interactor (C++):
#include "testlib.h"

#include <bits/stdc++.h>
#include <csignal>

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 string to_lower_ascii(string s) {
    for (char& c : s) c = (char)tolower((unsigned char)c);
    return s;
}

int main(int argc, char** argv) {
    registerInteraction(argc, argv);
    atexit(log_metrics);
#ifdef SIGPIPE
    signal(SIGPIPE, SIG_IGN);
#endif

    const int N = inf.readInt();
    if (N < 2 || N > 100) finish(_fail, "invalid N in hidden input");

    vector<pair<int, int>> edges;
    edges.reserve(max(0, N - 1));
    vector<vector<int>> adj(N + 1);
    vector<vector<unsigned char>> has_edge(N + 1, vector<unsigned char>(N + 1, 0));
    for (int i = 0; i < N - 1; i++) {
        int u = inf.readInt();
        int v = inf.readInt();
        if (u < 1 || u > N || v < 1 || v > N || u == v) finish(_fail, "invalid edge in hidden input");
        if (u > v) swap(u, v);
        if (has_edge[u][v]) finish(_fail, "duplicate edge in hidden input");
        has_edge[u][v] = has_edge[v][u] = 1;
        edges.push_back({u, v});
        adj[u].push_back(v);
        adj[v].push_back(u);
    }

    
    cout << N << "\n";
    for (auto [u, v] : edges) {
        cout << u << " " << v << "\n";
    }
    cout.flush();

    
    vector<int> color(N + 1, -1);
    queue<int> q;
    color[1] = 0;
    q.push(1);
    while (!q.empty()) {
        int x = q.front();
        q.pop();
        for (int y : adj[x]) {
            if (color[y] == -1) {
                color[y] = color[x] ^ 1;
                q.push(y);
            } else if (color[y] == color[x]) {
                finish(_fail, "hidden input graph is not bipartite");
            }
        }
    }
    for (int i = 1; i <= N; i++) {
        if (color[i] == -1) finish(_fail, "hidden input graph is not connected");
    }

    set<pair<int, int>> remaining;
    for (int i = 1; i <= N; i++) {
        for (int j = i + 1; j <= N; j++) {
            if (color[i] == color[j]) continue;
            if (has_edge[i][j]) continue;
            remaining.insert({i, j});
        }
    }
    query_limit = (long long)remaining.size();
    log_metrics();

    string role;
    if (!(cin >> role)) finish(_pe, "EOF (expected First/Second)");
    role = to_lower_ascii(role);

    bool contestant_first = false;
    if (role == "first") {
        contestant_first = true;
    } else if (role == "second") {
        contestant_first = false;
    } else {
        finish(_pe, "Invalid role (expected First/Second)");
    }

    bool contestant_turn = contestant_first;
    while (true) {
        if (contestant_turn) {
            int x, y;
            if (!(cin >> x >> y)) finish(_pe, "EOF (expected move)");

            if (x == -1 && y == -1) {
                if (remaining.empty()) finish(_wa, "Contestant cannot move (loses)");
                finish(_wa, "Contestant resigned with moves remaining");
            }

            if (x < 1 || x > N || y < 1 || y > N || x >= y) finish(_pe, "Invalid move format");
            if (has_edge[x][y]) finish(_wa, "Edge already exists");
            if (color[x] == color[y]) finish(_wa, "Move creates an odd cycle");

            auto it = remaining.find({x, y});
            if (it == remaining.end()) finish(_wa, "Illegal move");
            remaining.erase(it);
            has_edge[x][y] = has_edge[y][x] = 1;
            queries++;
            if (queries % 64 == 0) log_metrics();

            contestant_turn = false;
            continue;
        }

        
        if (remaining.empty()) {
            cout << -1 << " " << -1 << endl;  
            finish(_ok, "Contestant wins");
        }

        auto mv = *remaining.begin();
        remaining.erase(remaining.begin());
        has_edge[mv.first][mv.second] = has_edge[mv.second][mv.first] = 1;
        cout << mv.first << " " << mv.second << endl;
        if (!cout) finish(_pe, "Broken pipe while writing move");
        contestant_turn = true;
    }
}


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");
    
    
    long long seed_val = stoll(argv[1]);

    int N;
    int type = -1; 
    
    
    
    
    

    
    if (seed_val == 1) {
        N = 2; type = 3; 
    } else if (seed_val == 2) {
        N = 3; type = 3; 
    } else if (seed_val == 3) {
        N = 4; type = 2; 
    } else if (seed_val == 4) {
        N = 100; type = 3; 
    } else if (seed_val == 5) {
        N = 100; type = 2; 
    } else {
        
        
        int t = rnd.next(100);
        if (t < 10) N = rnd.next(2, 10);
        else if (t < 30) N = rnd.next(11, 50);
        else N = rnd.next(51, 100);

        
        int r = rnd.next(100);
        if (r < 50) type = 0;       
        else if (r < 80) type = 1;  
        else if (r < 90) type = 2;  
        else type = 3;              
    }

    vector<pair<int, int>> edges;

    if (type == 2) { 
        
        for (int i = 2; i <= N; i++) edges.push_back({1, i});
    } else if (type == 3) { 
        
        for (int i = 2; i <= N; i++) edges.push_back({i - 1, i});
    } else if (type == 1) { 
        
        
        
        int size_L = rnd.next(1, N - 1);
        
        vector<int> L_nodes, R_nodes;
        for (int i = 1; i <= size_L; i++) L_nodes.push_back(i);
        for (int i = size_L + 1; i <= N; i++) R_nodes.push_back(i);
        
        
        shuffle(L_nodes.begin(), L_nodes.end());
        shuffle(R_nodes.begin(), R_nodes.end());
        
        
        
        vector<int> connected_L, connected_R;
        vector<int> rem_L = L_nodes, rem_R = R_nodes;
        
        int u = rem_L.back(); rem_L.pop_back();
        int v = rem_R.back(); rem_R.pop_back();
        edges.push_back({u, v});
        connected_L.push_back(u);
        connected_R.push_back(v);
        
        
        while (!rem_L.empty() || !rem_R.empty()) {
            bool pick_L = false;
            if (rem_L.empty()) pick_L = false;
            else if (rem_R.empty()) pick_L = true;
            else pick_L = (rnd.next(2) == 0);
            
            if (pick_L) {
                int curr = rem_L.back(); rem_L.pop_back();
                int target = connected_R[rnd.next(connected_R.size())];
                edges.push_back({curr, target});
                connected_L.push_back(curr);
            } else {
                int curr = rem_R.back(); rem_R.pop_back();
                int target = connected_L[rnd.next(connected_L.size())];
                edges.push_back({curr, target});
                connected_R.push_back(curr);
            }
        }
    } else { 
        
        
        for (int i = 2; i <= N; i++) {
            edges.push_back({rnd.next(1, i - 1), i});
        }
    }

    
    vector<int> p(N);
    iota(p.begin(), p.end(), 1);
    shuffle(p.begin(), p.end());

    
    cout << N << endl;
    for (auto& e : edges) {
        int u = p[e.first - 1];
        int v = p[e.second - 1];
        if (u > v) swap(u, v);
        cout << u << " " << v << endl;
    }

    return 0;
}