Problem: cf1142_e
Difficulty: easy
Categories: graph
Time limit: 4000 ms, memory limit: 256 MB

This is an interactive task.

Scientists are about to invent a new optimization for the Floyd-Warshall algorithm, which will allow it to work in linear time. There is only one part of the optimization still unfinished.

It is well known that the Floyd-Warshall algorithm takes a graph with $n$ nodes and exactly one edge between each pair of nodes. The scientists have this graph, what is more, they have directed each edge in one of the two possible directions.

To optimize the algorithm, exactly $m$ edges are colored in pink color and all the rest are colored in green. You know the direction of all $m$ pink edges, but the direction of green edges is unknown to you. In one query you can ask the scientists about the direction of exactly one green edge, however, you can perform at most $2 \cdot n$ such queries.

Your task is to find the node from which every other node can be reached by a path consisting of edges of same color. Be aware that the scientists may have lied that they had fixed the direction of all edges beforehand, so their answers may depend on your queries.

Input

The first line contains two integers $n$ and $m$ ($1 \le n \le 100\,000$, $0 \le m \le 100\,000$) — the number of nodes and the number of pink edges.

The next $m$ lines describe the pink edges, the $i$-th of these lines contains two integers $u_i$, $v_i$ ($1 \le u_i, v_i \le n$, $u_i \ne v_i$) — the start and the end of the $i$-th pink edge. It is guaranteed, that all unordered pairs $(u_i, v_i)$ are distinct.

Output

When you found the answer, print "!" and the number of the node from which every other node can be reached by a single-colored path.

Interaction

To ask the direction of the green edge between nodes $a$ and $b$, print "?", $a$ and $b$ in single line, separated by the space characters.

In answer to this read a single integer, which will be $1$ if the edge is directed from $a$ to $b$ and $0$ if the edge is directed from $b$ to $a$.

You can ask at most $2 \cdot n$ queries, otherwise you will get Wrong Answer.

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.

Answer $-1$ instead of $0$ or $1$ means that you made an invalid query or exceeded the query limit. Exit immediately after receiving $-1$ and you will see Wrong answer verdict. Otherwise you can get an arbitrary verdict because your solution will continue to read from a closed stream.

Example

Input

```
4 2
1 2
3 4
0
1
1
```

Output

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

Note

In the example above the answer for the query "? 1 3" is 0, so the edge is directed from 3 to 1. The answer for the query "? 4 2" is 1, so the edge is directed from 4 to 2. The answer for the query "? 3 2" is 1, so the edge is directed from 3 to 2. So there are green paths from node 3 to nodes 1 and 2 and there is a pink path from node 3 to node 4.

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 int n = 0, m = 0;
static unsigned long long seed64 = 0;
static int root = -1; 

static unordered_set<unsigned long long> pinkPairs; 
static vector<pair<int,int>> pinkEdges;

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 unsigned long long pairKeyU64(int a, int b) {
    int x = min(a, b), y = max(a, b);
    return (static_cast<unsigned long long>(static_cast<unsigned int>(x)) << 32) |
           static_cast<unsigned long long>(static_cast<unsigned int>(y));
}

static unsigned long long mix64(unsigned long long x) {
    
    x += 0x9e3779b97f4a7c15ULL;
    x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9ULL;
    x = (x ^ (x >> 27)) * 0x94d049bb133111ebULL;
    x = x ^ (x >> 31);
    return x;
}


static bool greenDir(int a, int b) {
    if (a == b) return false;
    if (root != -1 && (a == root || b == root)) {
        
        return a == root;
    }
    int x = min(a, b), y = max(a, b);
    unsigned long long k = pairKeyU64(x, y);
    unsigned long long h = mix64(seed64 ^ (k * 0x9e3779b97f4a7c15ULL));
    bool minToMax = (h & 1ULL) != 0ULL;
    if (a == x) return minToMax;
    return !minToMax;
}

static vector<int> computeAllSolutionsBruteforce() {
    
    int N = n;
    int words = (N + 63) / 64;

    auto makeBits = [&]() { return vector<unsigned long long>(words, 0ULL); };
    vector<vector<unsigned long long>> pinkReach(N + 1), greenReach(N + 1);
    for (int i = 1; i <= N; i++) {
        pinkReach[i] = makeBits();
        greenReach[i] = makeBits();
        pinkReach[i][(i - 1) >> 6] |= 1ULL << ((i - 1) & 63);
        greenReach[i][(i - 1) >> 6] |= 1ULL << ((i - 1) & 63);
    }

    
    for (auto &e : pinkEdges) {
        int u = e.first, v = e.second;
        pinkReach[u][(v - 1) >> 6] |= 1ULL << ((v - 1) & 63);
    }

    
    for (int i = 1; i <= N; i++) {
        for (int j = i + 1; j <= N; j++) {
            unsigned long long k = pairKeyU64(i, j);
            if (pinkPairs.find(k) != pinkPairs.end()) continue;
            bool iToJ = greenDir(i, j);
            if (iToJ) greenReach[i][(j - 1) >> 6] |= 1ULL << ((j - 1) & 63);
            else greenReach[j][(i - 1) >> 6] |= 1ULL << ((i - 1) & 63);
        }
    }

    auto closure = [&](vector<vector<unsigned long long>> &reach) {
        for (int k = 1; k <= N; k++) {
            int kw = (k - 1) >> 6;
            unsigned long long kmask = 1ULL << ((k - 1) & 63);
            for (int i = 1; i <= N; i++) {
                if ((reach[i][kw] & kmask) == 0ULL) continue;
                for (int w = 0; w < words; w++) reach[i][w] |= reach[k][w];
            }
        }
    };

    closure(pinkReach);
    closure(greenReach);

    vector<int> sols;
    for (int s = 1; s <= N; s++) {
        bool ok = true;
        for (int v = 1; v <= N; v++) {
            int w = (v - 1) >> 6;
            unsigned long long mask = 1ULL << ((v - 1) & 63);
            bool pr = (pinkReach[s][w] & mask) != 0ULL;
            bool gr = (greenReach[s][w] & mask) != 0ULL;
            if (!pr && !gr) {
                ok = false;
                break;
            }
        }
        if (ok) sols.push_back(s);
    }
    return sols;
}

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

    try {
        n = inf.readInt(1, 100000, "n");
        m = inf.readInt(0, 100000, "m");
        query_limit = 2LL * n;

        pinkEdges.reserve(m);
        pinkPairs.reserve(static_cast<size_t>(m) * 2 + 10);

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

        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, "Invalid hidden input: self-loop pink edge");
            unsigned long long k = pairKeyU64(u, v);
            if (pinkPairs.find(k) != pinkPairs.end())
                finish(_fail, "Invalid hidden input: duplicated unordered pink pair");
            pinkPairs.insert(k);
            pinkEdges.push_back({u, v});
            pinkInc[u]++;
            pinkInc[v]++;
        }

        
        long long last = inf.readLong();
        if (last < 0) last = -last;
        seed64 = static_cast<unsigned long long>(last);

        
        root = -1;
        for (int i = 1; i <= n; i++) {
            if (pinkInc[i] == 0) {
                root = i;
                break;
            }
        }

        
        log_metrics();

        
        cout << n << " " << m << "\n";
        for (auto &e : pinkEdges) cout << e.first << " " << e.second << "\n";
        cout.flush();

        
        vector<int> acceptable;
        if (root != -1) {
            
            acceptable.push_back(root);
        } else {
            
            acceptable = computeAllSolutionsBruteforce();
        }

        auto isAcceptable = [&](int x) -> bool {
            for (int v : acceptable) if (v == x) return true;
            return false;
        };

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

        string op;
        while (cin >> op) {
            if (op == "?") {
                long long a_ll, b_ll;
                if (!(cin >> a_ll >> b_ll)) finish(_pe, "Malformed query: missing a b");
                if (a_ll < 1 || a_ll > n || b_ll < 1 || b_ll > n || a_ll == b_ll) {
                    cout << -1 << "\n";
                    cout.flush();
                    finish(_wa, "Invalid query parameters");
                }
                int a = (int)a_ll, b = (int)b_ll;
                unsigned long long k = pairKeyU64(a, b);
                if (pinkPairs.find(k) != pinkPairs.end()) {
                    cout << -1 << "\n";
                    cout.flush();
                    finish(_wa, "Queried a pink edge");
                }

                queries++;
                if (queries > hard_cap) finish(_pe, "Hard cap exceeded");

                int ans = greenDir(a, b) ? 1 : 0;
                cout << ans << "\n";
                cout.flush();
            } else if (op == "!") {
                long long x_ll;
                if (!(cin >> x_ll)) finish(_pe, "Malformed answer: missing vertex");
                if (x_ll < 1 || x_ll > n) finish(_wa, "Answer out of range");
                int x = (int)x_ll;

                if (acceptable.empty()) {
                    finish(_wa, "No acceptable answers (invalid hidden instance)");
                }
                if (isAcceptable(x)) finish(_ok, "OK");
                finish(_wa, "Wrong answer");
            } else {
                finish(_pe, "Unexpected token (expected '?' or '!')");
            }
        }

        finish(_wa, "EOF without final answer");
    } catch (const std::exception& e) {
        finish(_fail, string("Exception: ") + e.what());
    } catch (...) {
        finish(_fail, "Unknown exception");
    }
}


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 long long pairKey(int a, int b) {
    int x = min(a, b), y = max(a, b);
    return (static_cast<long long>(x) << 32) ^ static_cast<unsigned long long>(y);
}

static bool parseLL(const string& s, long long& out) {
    if (s.empty()) return false;
    int i = 0;
    bool neg = false;
    if (s[i] == '-') {
        neg = true;
        i++;
        if (i == (int)s.size()) return false;
    }
    long long val = 0;
    for (; i < (int)s.size(); i++) {
        char c = s[i];
        if (c < '0' || c > '9') return false;
        int d = c - '0';
        if (val > (LLONG_MAX - d) / 10) return false;
        val = val * 10 + d;
    }
    out = neg ? -val : val;
    return true;
}

static bool readToken(string& tok) {
    if (!(cin >> tok)) return false;
    return true;
}

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

    int n = inf.readInt(1, 100000, "n");
    int m = inf.readInt(0, 100000, "m");

    vector<pair<int,int>> pinkEdges;
    pinkEdges.reserve(m);

    unordered_set<long long> pinkPairs;
    pinkPairs.reserve((size_t)m * 2 + 10);

    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, "invalid pink edge in input (self-loop)");
        long long k = pairKey(u, v);
        if (pinkPairs.find(k) != pinkPairs.end()) finish(_fail, "duplicate pink unordered pair in input");
        pinkPairs.insert(k);
        pinkEdges.push_back({u, v});
    }

    int x = 1;
    if (!inf.seekEof()) {
        string tail = inf.readToken();
        long long z;
        if (!parseLL(tail, z)) finish(_fail, "invalid trailing token in input");
        if (1 <= z && z <= n) {
            x = (int)z;
        } else {
            long long zz = z;
            if (zz < 0) zz = -zz;
            x = (int)(zz % n) + 1;
        }
    }

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

    cout << n << " " << m << "\n";
    for (auto &e : pinkEdges) cout << e.first << " " << e.second << "\n";
    cout.flush();

    log_metrics(); 

    unordered_map<long long, unsigned char> greenDirMinToMax;
    greenDirMinToMax.reserve((size_t)min(hard_cap, 400000LL) * 2 + 10);

    auto rankOf = [&](int v) -> int {
        if (v == x) return n + 1;
        return v;
    };

    auto getDirMinToMax = [&](int a, int b) -> unsigned char {
        int mn = min(a, b), mx = max(a, b);
        long long k = pairKey(mn, mx);
        auto it = greenDirMinToMax.find(k);
        if (it != greenDirMinToMax.end()) return it->second;

        int ra = rankOf(mn);
        int rb = rankOf(mx);
        unsigned char dir = (ra > rb) ? 1 : 0; 
        greenDirMinToMax.emplace(k, dir);
        return dir;
    };

    string cmd;
    while (true) {
        if (!readToken(cmd)) finish(_pe, "unexpected EOF (no final answer)");
        if (cmd == "?") {
            string sa, sb;
            if (!readToken(sa) || !readToken(sb)) {
                cout << -1 << "\n";
                cout.flush();
                finish(_wa, "incomplete query");
            }
            long long la, lb;
            if (!parseLL(sa, la) || !parseLL(sb, lb)) {
                cout << -1 << "\n";
                cout.flush();
                finish(_wa, "non-integer in query");
            }
            if (la < 1 || la > n || lb < 1 || lb > n || la == lb) {
                cout << -1 << "\n";
                cout.flush();
                finish(_wa, "query out of range or self-loop");
            }
            int a = (int)la, b = (int)lb;

            long long k = pairKey(a, b);
            if (pinkPairs.find(k) != pinkPairs.end()) {
                cout << -1 << "\n";
                cout.flush();
                finish(_wa, "queried a pink edge");
            }

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

            int mn = min(a, b), mx = max(a, b);
            unsigned char dirMnToMx = getDirMinToMax(a, b);

            int ans = 0;
            if (a == mn && b == mx) ans = (dirMnToMx ? 1 : 0);
            else ans = (dirMnToMx ? 0 : 1);

            cout << ans << "\n";
            cout.flush();
        } else if (cmd == "!") {
            string sv;
            if (!readToken(sv)) finish(_pe, "missing answer vertex after '!'");
            long long lv;
            if (!parseLL(sv, lv) || lv < 1 || lv > n) finish(_wa, "invalid answer vertex");
            int v = (int)lv;

            if (v == x) finish(_ok, "correct");
            finish(_wa, "wrong vertex");
        } else {
            finish(_pe, "invalid command token");
        }
    }
}


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

static long long pairKey(int a, int b) {
    int x = min(a, b), y = max(a, b);
    return (static_cast<long long>(x) << 32) ^ static_cast<unsigned long long>(y);
}

static vector<pair<int,int>> buildPinkEdges(int n, int m, int avoid) {
    vector<int> nodes;
    nodes.reserve(n - (avoid ? 1 : 0));
    for (int i = 1; i <= n; i++) if (i != avoid) nodes.push_back(i);

    unordered_set<long long> used;
    used.reserve(static_cast<size_t>(m) * 2 + 10);

    vector<pair<int,int>> edges;
    edges.reserve(m);

    auto tryAdd = [&](int u, int v, bool uToV) -> bool {
        if (u == v) return false;
        long long k = pairKey(u, v);
        if (used.find(k) != used.end()) return false;
        used.insert(k);
        edges.push_back(uToV ? make_pair(u, v) : make_pair(v, u));
        return true;
    };

    int L = (int)nodes.size();

    
    for (int i = 0; i + 1 < L && (int)edges.size() < m; i++) {
        int a = nodes[i], b = nodes[i + 1];
        bool aToB = (i % 2 == 0);
        tryAdd(a, b, aToB);
    }

    
    int half = L / 2;
    for (int i = 0; i < half && (int)edges.size() < m; i++) {
        int a = nodes[i], b = nodes[i + half];
        bool aToB = ((i % 3) == 0);
        tryAdd(a, b, aToB);
    }

    
    while ((int)edges.size() < m) {
        int ia = rnd.next(0, L - 1);
        int ib = rnd.next(0, L - 1);
        if (ia == ib) continue;
        int a = nodes[ia], b = nodes[ib];
        bool aToB = (rnd.next(0, 1) == 1);
        tryAdd(a, b, aToB);
    }

    return edges;
}

int main(int argc, char* argv[]) {
    registerGen(argc, argv, 1);
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    string mode = opt<string>("mode", "non");

    long long seedNum = 0;
    if (argc >= 2) seedNum = atoll(argv[1]);

    int n = opt<int>("n", 100000);
    int m = opt<int>("m", 100000);

    if (seedNum == 1) {
        n = 1; m = 0;
        if (mode == "non") {
            cout << n << " " << m << "\n";
            long long S = rnd.next(1LL, 4000000000000000000LL);
            cout << S << "\n";
        } else if (mode == "adp") {
            cout << n << " " << m << "\n";
            cout << 1 << "\n";
        } else {
            quitf(_fail, "Unknown mode: %s", mode.c_str());
        }
        return 0;
    }

    if (seedNum == 2) {
        
        n = 3; m = 3;
        if (mode == "non") {
            cout << n << " " << m << "\n";
            cout << 1 << " " << 2 << "\n";
            cout << 2 << " " << 3 << "\n";
            cout << 3 << " " << 1 << "\n";
            long long S = rnd.next(1LL, 4000000000000000000LL);
            cout << S << "\n";
        } else if (mode == "adp") {
            cout << n << " " << m << "\n";
            cout << 1 << " " << 2 << "\n";
            cout << 2 << " " << 3 << "\n";
            cout << 3 << " " << 1 << "\n";
            cout << 1 << "\n";
        } else {
            quitf(_fail, "Unknown mode: %s", mode.c_str());
        }
        return 0;
    }

    if (seedNum == 3) {
        
        n = 100000;
        m = 100000;
    }

    if (n < 1) n = 1;
    if (m < 0) m = 0;
    long long maxPairs = 1LL * n * (n - 1) / 2;
    if (m > maxPairs) m = (int)maxPairs;

    if (mode == "non") {
        int avoid = (n == 1 ? 0 : rnd.next(1, n));
        
        if (n >= 2 && m > 0) {
            long long maxPairsAvoid = 1LL * (n - 1) * (n - 2) / 2;
            if (m > maxPairsAvoid) avoid = 0; 
        }
        auto edges = buildPinkEdges(n, m, avoid);

        cout << n << " " << m << "\n";
        for (auto &e : edges) cout << e.first << " " << e.second << "\n";
        long long S = rnd.next(1LL, 4000000000000000000LL);
        cout << S << "\n";
    } else if (mode == "adp") {
        int x = (n == 1 ? 1 : rnd.next(1, n));
        
        int avoid = x;
        if (n >= 2 && m > 0) {
            long long maxPairsAvoid = 1LL * (n - 1) * (n - 2) / 2;
            if (m > maxPairsAvoid) avoid = 0; 
        }
        auto edges = buildPinkEdges(n, m, avoid);

        cout << n << " " << m << "\n";
        for (auto &e : edges) cout << e.first << " " << e.second << "\n";
        cout << x << "\n";
    } else {
        quitf(_fail, "Unknown mode: %s", mode.c_str());
    }

    return 0;
}