#include <cstdio>  // {{{
#include <iostream>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <algorithm>

#define GET_MACRO(a, b, c, d, NAME, ...) NAME
#define REP(...) GET_MACRO(__VA_ARGS__, REP4, REP3, REP2)(__VA_ARGS__)
#define REP2(i, a) REP3(i, 0, a)
#define REP3(i, a, b) REP4(i, a, b, 1)
#define REP4(i, a, b, s) for (int i = (a); i < (int)(b); i += (s))
#define REPR(...) GET_MACRO(__VA_ARGS__, REPR4, REPR3, REPR2)(__VA_ARGS__)
#define REPR2(i, a) REPR3(i, 0, a)
#define REPR3(i, a, b) REPR4(i, a, b, 1)
#define REPR4(i, a, b, s) for (int i = (b)-1; i >= (int)(a); i -= (s))
#define ALL(c) (c).begin(), (c).end()

using Int = long long;
// clang-format off
template<typename T,typename U>inline bool chmax(T&x,U a){return x<a&&(x=a,1);}
template<typename T,typename U>inline bool chmin(T&x,U a){return a<x&&(x=a,1);}
inline signed in(){signed x;scanf("%d",&x);return x;}
// clang-format on
// }}}

//{{{ graph.hpp
#ifndef INCLUDE_GRAPH_HPP
#define INCLUDE_GRAPH_HPP
#include <vector>
#include <climits>
namespace orliv {
namespace graph {
struct Edge {
  using weight_type = int;
  static constexpr weight_type INF =
      std::numeric_limits<weight_type>::max() - 100;

  int from, to;
  weight_type w;
  Edge(int from, int to, weight_type w = 1) : from(from), to(to), w(w) {}
  bool operator<(const Edge& rhs) const {
    if (w != rhs.w) return w > rhs.w;
    if (from != rhs.from) return from < rhs.from;
    return to < rhs.to;
  }
};

using Weight = Edge::weight_type;
using Edges = std::vector<Edge>;
using Weights = std::vector<Weight>;
using Path = std::vector<int>;
using Nodes = std::vector<int>;
}
using Graph = std::vector<graph::Edges>;
}
#endif
//}}}
#ifndef INCLUDE_GRAPH_HPP
#include "graph.hpp"
#endif
#include <numeric>

namespace orliv {
namespace graph {
struct DomTree {
  struct UnionFind {
    const std::vector<int>& semi;
    std::vector<int> par, m;
    UnionFind(const std::vector<int>& semi)
        : semi(semi), par(semi.size()), m(semi.size()) {
      std::iota(par.begin(), par.end(), 0);
      std::iota(m.begin(), m.end(), 0);
    }
    int find(int v) {
      if (par[v] == v) return v;
      int r = find(par[v]);
      if (semi[m[v]] > semi[m[par[v]]]) m[v] = m[par[v]];
      return par[v] = r;
    }
    int eval(int v) {
      find(v);
      return m[v];
    }
    void link(int p, int c) { par[c] = p; }
  };
  std::vector<std::vector<int>> G, rG, bucket;
  std::vector<int> par, semi, ord, U, idom;
  UnionFind uni;
  DomTree(int V)
      : G(V), rG(V), bucket(V), par(V), semi(V, -1), U(V), idom(V), uni(semi) {
    ord.reserve(V);
  }
  void dfs(int v) {
    semi[v] = ord.size();
    ord.emplace_back(v);
    for (int u : G[v]) {
      if (semi[u] >= 0) continue;
      par[u] = v;
      dfs(u);
    }
  }
  void build(int r) {
    const int N = G.size();
    dfs(r);
    for (int i = N - 1; i > 0; --i) {
      int x = ord[i];
      for (int v : rG[x]) {
        int u = uni.eval(v);
        if (semi[x] > semi[u]) semi[x] = semi[u];
      }
      bucket[ord[semi[x]]].emplace_back(x);
      for (int v : bucket[par[x]]) U[v] = uni.eval(v);
      bucket[par[x]].clear();
      uni.link(par[x], x);
    }
    for (int i = 1; i < N; i++) {
      int x = ord[i], u = U[x];
      idom[x] = semi[x] == semi[u] ? semi[x] : idom[u];
    }
    for (int i = 1; i < N; i++) {
      int x = ord[i];
      idom[x] = ord[idom[x]];
    }
    idom[r] = -1;
  }
  int get(int v) const { return idom[v]; }

  template <typename... Types>
  void add(Types... args) {
    Edge e(std::forward<Types>(args)...);
    G[e.from].emplace_back(e.to);
    rG[e.to].emplace_back(e.from);
  }
};
}
}

using namespace std;

signed main() {
  int N = in(), M = in();
  orliv::graph::DomTree domtree(N);
  REP(i, M) {
    int a = in() - 1, b = in() - 1;
    domtree.add(a, b);
  }
  domtree.build(0);

  int Q = in();
  REP(i, Q) {
    int v = in() - 1;
    int ans = domtree.get(v);
    if (ans == 0) ans = v;
    printf("%d\n", ans + 1);
  }
  return 0;
}

Measured memory_bytes: 22304