//#define _GLIBCXX_DEBUG
#include <bits/stdc++.h>
using namespace std;
#if __has_include(<atcoder/all>)
   #include <atcoder/all>
   using namespace atcoder;
#endif
#define all(v) v.begin(), v.end()
using in = long long;
#define rep(i, n) for (int i = 0; i < (int)(n); i++)
#define REP(i,a,b) for(int i=(int)(a);i<(int)(b);i++)
#define Yes cout<<"Yes"<<endl
#define No cout<<"No"<<endl
#define yes cout<<"yes"<<endl
#define no cout<<"no"<<endl
#define YES cout<<"YES"<<endl
#define NO cout<<"NO"<<endl
const int inf=max(int(1e18)+7,int(1e9)+7);
using P=pair<int,int>;
using T=tuple<int,int,int>;
vector<int> dx={0,1,-1,0};
vector<int> dy={1,0,0,-1};
template <typename Typ>
bool chmin(Typ &a, const Typ& b) {if (a > b) {a = b; return true;} return false;}
template <typename Typ>
bool chmax(Typ &a, const Typ& b) {if (a < b) {a = b; return true;} return false;}
template <typename Typ>
Typ ceil(Typ x, Typ y){return (x+y-1)/y;}
#ifdef  _DEBUG
    #define debug(x) cout<<"debug:"<<x<<endl
    #define vdebug(x) cout<<"debug:";\
                      for(auto asdf:x) cout<<asdf<<" ";\
                      cout<<endl
#else
    #define debug(x) 
    #define vdebug(x) 
#endif
#define CASE(x) cout<<"Case #"<<x<<": "

//辺でカウント
vector<int> en(0),ex(0),vis(0);
vector<int> ran_f(0),ran_l(0);
vector<int> depth(0);
vector<int> par(0);
vector<vector<int>> tree(0);
int cnt=0;

void tour(int ed){
    int n = par.size();
    if(en.empty()){
        en.resize(n,-1);
        ex.resize(n,-1);
        ran_f.resize(n,-1);
        ran_l.resize(n,-1);
        depth.resize(n,-1);
        depth[ed] = 0;
    }

    en[ed] = cnt;
    cnt ++;
    vis.emplace_back(ed);
    ran_f[ed] = vis.size()-1;
    ran_l[ed] = vis.size()-1;

    for(auto nxt:tree[ed]){
        depth[nxt] = depth[ed]+1;
        tour(nxt);
        vis.emplace_back(ed);
        ran_l[ed] = vis.size()-1;
    }
    ex[ed] = cnt;
    cnt ++;
    return;
}

int main(){
ios::sync_with_stdio(false);cin.tie(nullptr);
//cout << fixed << setprecision(12);
    int n;  cin>>n;
    vector<int> p(n,0);
    REP(i,1,n){
        cin>>p[i];
        p[i]--;
    }
    int q;  cin>>q;
    vector<int> u(q),d(q);
        rep(i,q) cin>>u[i]>>d[i];
        rep(i,q) u[i]--;
    
    par = p;
    tree = vector<vector<int>>(n,vector<int>(0));
    REP(i,1,n) tree[p[i]].emplace_back(i);
    tour(0);
    map<int,vector<int>> mp;
    rep(i,n) mp[depth[i]].emplace_back(en[i]);
    for(auto& [ignore,x]:mp) sort(all(x));

    rep(i,q){
        int x=u[i],y=d[i];
        int s=en[x],t=ex[x];
        int ans = upper_bound(all(mp[y]),t)-lower_bound(all(mp[y]),s);
        cout<<ans<<"\n";
        
    }


    // vdebug(en);
    // vdebug(ex);
    // vdebug(ran_f);
    // vdebug(ran_l);
    // vdebug(vis);
}/*
./problem.exe
*/
#include <bits/stdc++.h>

using namespace std;

struct DSU {
    vector<int> ps;
    vector<vector<int>> children;
    DSU(int n): ps(n), children(n) {
        iota(ps.begin(), ps.end(), 0);
        for (int i = 0; i < n; ++i) {
            children[i].push_back(i);
        }
    }
    int find(int i) {
        if (ps[i] == i) {
            return i;
        }
        return ps[i] = find(ps[i]);
    }
    bool merge(int i, int j) {
        i = find(i);
        j = find(j);
        if (i == j) {
            return false;
        }
        if (children[i].size() > children[j].size()) {
            swap(i, j);
        }
        ps[i] = j;
        children[j].insert(children[j].end(), children[i].begin(), children[i].end());
        return true;
    }
};


void solve() {
    int n, m;
    cin >> n >> m;
    vector<pair<int, int>> edges(m);
    map<pair<int, int>, int> edges_dir; // -1 = not set, 0 = org, 1 = reverse
    for (auto& edge : edges) {
        int u, v;
        cin >> u >> v;
        --u;
        --v;
        edge = {u, v};
        edges_dir[edge] = -1;
    }
    vector<int> cs(n);
    for (int& c : cs) {
        cin >> c;
    }
    vector<vector<int>> adj_list(n);
    for (auto& edge : edges) {
        int u, v;
        tie(u, v) = edge;
        if (cs[u] != cs[v]) {
            edges_dir[edge] = cs[u] > cs[v] ? 0 : 1;
        } else {
            adj_list[u].push_back(v);
            adj_list[v].push_back(u);
        }
    }
    DSU dsu(n);
    for (int u = 0; u < n; ++u) {
        set<int> seen;
        stack<int> seen_order;
        stack<pair<int, int>> edge_order;
        set<pair<int, int>> used_edges;
        function<bool (int)> dfs = [&](int v) {
            v = dsu.find(v);
            seen_order.push(v);
            if (seen.count(v)) {
                return true;
            }
            seen.insert(v);
            for (int w : dsu.children[v]) {
                for (int z : adj_list[w]) {
                    if (dsu.find(z) != v && !used_edges.count({w, z})) {
                        used_edges.insert({w, z});
                        used_edges.insert({z, w});
                        edge_order.push({w, z});
                        if (dfs(z)) {
                            return true;
                        }
                        edge_order.pop();
                    }
                }
            }
            seen_order.pop();
            return false;
        };
        if (dfs(u)) {
            assert (seen_order.size() == edge_order.size() + 1);
            int v = seen_order.top();
            seen_order.pop();
            vector<int> cycle = {v};
            while (true) {
                int w = seen_order.top();
                seen_order.pop();
                if (w == v) {
                    break;
                }
                cycle.push_back(w);
            }
            int cycle_size = (int) cycle.size();
            for (int i = 0; i < cycle_size; ++i) {
                assert (!edge_order.empty());
                int u0, v0;
                tie(u0, v0) = edge_order.top();
                edge_order.pop();
                if (edges_dir.count({u0, v0})) {
                    assert ((edges_dir[{u0, v0}] == -1));
                    edges_dir[{u0, v0}] = 0;
                } else {
                    assert (edges_dir.count({v0, u0}));
                    assert ((edges_dir[{v0, u0}] == -1));
                    edges_dir[{v0, u0}] = 1;
                }
            }
            for (int w : cycle) {
                dsu.merge(w, v);
            }
            --u;
        }
    }
    for (auto& edge : edges) {
        if (edges_dir[edge] == 1) {
            cout << "<-\n";
        } else {
            cout << "->\n";
        }
    }
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    solve();
    return 0;
}