#include <bits/stdc++.h>
using namespace std;
template <class c>
struct rge {
  c b, e;
};
template <class c>
rge<c> range(c i, c j) {
  return rge<c>{i, j};
}
template <class c>
auto dud(c *x) -> decltype(cerr << *x, 0);
template <class c>
char dud(...);
struct debug {
  template <class c>
  debug &operator<<(const c &) {
    return *this;
  }
};
using ll = long long;
vector<vector<int>> all;
class Graph {
  int V;
  list<int> *adj;
  void fillOrder(int v, bool visited[], stack<int> &Stack);
  void DFSUtil(int v, bool visited[]);

 public:
  Graph(int V);
  void addEdge(int v, int w);
  void printSCCs();
  Graph getTranspose();
};
Graph::Graph(int _V) {
  this->V = _V;
  adj = new list<int>[_V];
}
vector<int> last;
void Graph::DFSUtil(int v, bool visited[]) {
  visited[v] = true;
  last.push_back(v);
  list<int>::iterator i;
  for (i = adj[v].begin(); i != adj[v].end(); ++i)
    if (!visited[*i]) DFSUtil(*i, visited);
}
Graph Graph::getTranspose() {
  Graph g(V);
  for (int v = 0; v < V; v++) {
    list<int>::iterator i;
    for (i = adj[v].begin(); i != adj[v].end(); ++i) {
      g.adj[*i].push_back(v);
    }
  }
  return g;
}
void Graph::addEdge(int v, int w) { adj[v].push_back(w); }
void Graph::fillOrder(int v, bool visited[], stack<int> &Stack) {
  visited[v] = true;
  list<int>::iterator i;
  for (i = adj[v].begin(); i != adj[v].end(); ++i)
    if (!visited[*i]) fillOrder(*i, visited, Stack);
  Stack.push(v);
}
void Graph::printSCCs() {
  stack<int> Stack;
  bool *visited = new bool[V];
  for (int i = 0; i < V; i++) visited[i] = false;
  for (int i = 0; i < V; i++)
    if (visited[i] == false) fillOrder(i, visited, Stack);
  Graph gr = getTranspose();
  for (int i = 0; i < V; i++) visited[i] = false;
  while (Stack.empty() == false) {
    int v = Stack.top();
    Stack.pop();
    if (visited[v] == false) {
      last.clear();
      gr.DFSUtil(v, visited);
      all.push_back(last);
    }
  }
}
const int nax = 2e5 + 5;
int gg[nax];
vector<int> inv[nax];
int in[nax];
vector<int> memo[nax];
int main() {
  int n, m;
  scanf("%d%d", &n, &m);
  Graph gr(n);
  vector<pair<int, int>> edges;
  for (int i = 0; i < m; ++i) {
    int a, b;
    scanf("%d%d", &a, &b);
    --a;
    --b;
    gr.addEdge(a, b);
    edges.emplace_back(a, b);
    memo[a].push_back(b);
  }
  gr.printSCCs();
  debug() << " ["
          << "all"
             ": "
          << (all) << "] ";
  for (int i = 0; i < (int)all.size(); ++i) {
    inv[i] = all[i];
    for (int x : all[i]) {
      gg[x] = i;
    }
  }
  for (pair<int, int> p : edges) {
    if (gg[p.first] != gg[p.second]) {
      ++in[gg[p.second]];
    }
  }
  int a = -1;
  for (int i = 0; i < n; ++i) {
    if (!in[gg[i]]) {
      a = i;
      break;
    }
  }
  assert(a != -1);
  set<int> ggs;
  for (int i = 0; i < (int)all.size(); ++i) {
    if (in[i] == 0) {
      ggs.insert(i);
    }
  }
  {
    int me = gg[a];
    for (int i = 0; i < (int)inv[me].size(); ++i) {
      if (inv[me][i] == a) {
        swap(inv[me][i], inv[me].back());
        inv[me].pop_back();
      }
    }
  }
  auto rem = [&](int g) {
    g = gg[g];
    if (!inv[g].empty()) {
      return;
    }
    for (int x : all[g]) {
      for (int y : memo[x]) {
        if (gg[x] == gg[y]) {
          continue;
        }
        if (--in[gg[y]] == 0) {
          ggs.insert(gg[y]);
        }
        assert(in[gg[y]] >= 0);
      }
    }
    ggs.erase(g);
  };
  while (true) {
    int me = gg[a];
    if ((int)ggs.size() == 1) {
      assert(ggs == set<int>{me});
      break;
    }
    auto it = ggs.find(me);
    if (it == ggs.begin()) {
      ++it;
    } else {
      --it;
    }
    int he = *it;
    int b = inv[he].back();
    inv[he].pop_back();
    printf("? %d %d\n", a + 1, b + 1);
    fflush(stdout);
    int r;
    scanf("%d", &r);
    if (r == 1) {
      rem(b);
    } else {
      assert(r == 0);
      rem(a);
      a = b;
    }
  }
  printf("! %d\n", a + 1);
}
