Problem:
C: な◯りカット (Namo.. Cut)
問題
－謎の巨大クラゲ、 コードネーム「な◯り」を討伐せよ－
「な◯り」は非常に生命力が強いため、素早く切断し続けなければ、あっという間に復活してしまう。
我々は、「な◯り」をどのように切断するのが効率良いのか、日々試行錯誤している。
その過程で、あなた方プログラマの手が必要になった。
「な◯り」は
N
頂点と
N
辺からなる連結な無向グラフで表現できる。
以降、各頂点が
1
から
N
の異なる数で名前付けられているとしよう。
我々は、「な◯り」に関して
Q
回の質問を行う。
それらすべてに答えるプログラムを作成して欲しい。
質問は
1
から
Q
の番号を持ち、各質問は次のように構成される。
質問
i
では 2 つの頂点
a_i
と
b_i
が指定される。
a_i
と
b_i
を非連結にするために、削除する必要のある辺の最小本数を答えよ。
ここで、頂点
u
と
v
が非連結であるとは、
u
と
v
を行き来できる経路が存在しないことを指す。
入力形式
N
u_1
v_1
u_2
v_2
...
u_N
v_N
Q
a_1
b_1
a_2
b_2
...
a_Q
b_Q
入力はすべて整数である。
1 行目には頂点数
N
が与えられる。 
続く
N
行のうち
i
行目には、
i
番目の辺が繋ぐ 2 頂点の番号
u_i, v_i
が空白区切りで与えられる。
次に、質問の回数
Q
が与えられる。
続く
Q
行のうち
i
行目には、
i
番目の質問で指定される 2 頂点の番号
a_i, b_i
が空白区切りで与えられる。
制約
3 \leq N \leq 100,000
1 \leq Q \leq 100,000
グラフに自己ループ及び多重辺は存在しない
1 \leq a_i, b_i \leq N
かつ
a_i \neq b_i
(
1 \leq i \leq Q
)
出力形式
出力は
Q
行からなる。
i
行目には、
a_i
と
b_i
を非連結にするために、削除する必要のある辺の最小本数を表す整数を出力せよ。
入力例1
3
1 2
1 3
2 3
1
1 3
出力例1
2
入力例2
7
1 2
1 6
3 5
2 5
5 4
1 4
3 7
3
2 4
3 1
6 7
出力例2
2
1
1

Submitted solutions:

code_snippet: #include <iostream>
#include <vector>
#include <stack>
#include <set>

using namespace std;

vector<vector<int>> G;
vector<int> seen;
vector<int> finished;
stack<int> cycle;


int DFS(int now, int parent, int cycleIndex){
    seen[now] = true;
    cycle.push(now);

    for (auto g: G[now]){
        // 逆流防止
        if (g == parent) continue;
        // 帰りがけ探索完了
        if (finished[g]) continue;

        // 帰りがけ探索が完了していないのに、２回目の訪問＝サイクルあり
        if (seen[g] && !finished[g]) return g;

        cycleIndex = DFS(g, now, cycleIndex);

        //サイクルを検知した時点で、探索を停止
        if (cycleIndex >= 0) return cycleIndex;
    }

    cycle.pop();
    finished[now] = true;
    return cycleIndex;
}

int main(){
    int N;
    cin >> N;
    
    G.assign(N, vector<int>());
    
    int u, v;
    for(int i=0; i<N; i++){
        cin >> u >> v;
        G[u-1].push_back(v-1);
        G[v-1].push_back(u-1);
    }

    seen.assign(N, false);
    finished.assign(N, false);

    int cycleIndex;
    DFS(0, -1, -1);
    
    set<int> cycleSet;
    while(!cycle.empty()){
        int n = cycle.top();
        cycle.pop();
        if (finished[n]) continue;
        cycleSet.insert(n);
        // if (n == cycleIndex) break;
    }

    int Q;
    cin >> Q;

    for (int i=0; i<Q; i++){
        int a, b;
        cin >> a >> b;
        a--;
        b--;
        if (cycleSet.count(a) && cycleSet.count(b)) cout << 2 << endl;
        else cout << 1 << endl;
    }

    return 0;
}
accuracy: 0.046511627906976744
time_ms: 60
memory_kb: 8760
final_rank: 19

code_snippet: #include <iostream>
#include <vector>
#include <stack>
#include <set>

using namespace std;

vector<vector<int>> G;
vector<int> seen;
vector<int> finished;
stack<int> cycle;

int pos = -1;

void DFS(int now, int parent){
    seen[now] = true;
    cycle.push(now);

    for (auto g: G[now]){
        // 逆流防止
        if (g == parent) continue;
        // 帰りがけ探索完了
        if (finished[g]) continue;

        // 帰りがけ探索が完了していないのに、２回目の訪問＝サイクルあり
        if (seen[g] && !finished[g]) {
            pos = g;
            return;
        }

        DFS(g, now);

        //サイクルを検知した時点で、探索を停止
        if (pos != -1) return ;
    }

    cycle.pop();
    finished[now] = true;

}

int main(){
    int N;
    cin >> N;
    
    G.assign(N, vector<int>());
    
    int u, v;
    for(int i=0; i<N; i++){
        cin >> u >> v;
        G[u-1].push_back(v-1);
        G[v-1].push_back(u-1);
    }

    seen.assign(N, false);
    finished.assign(N, false);

    DFS(0, -1);
    
    set<int> cycleSet;
    while(!cycle.empty()){
        int n = cycle.top();
        cycleSet.insert(n);
        cycle.pop();
        if (n == pos) break;
        // if (n == cycleIndex) break;
    }

    int Q;
    cin >> Q;

    for (int i=0; i<Q; i++){
        int a, b;
        cin >> a >> b;
        a--;
        b--;
        if (cycleSet.count(a) && cycleSet.count(b)) cout << 2 << endl;
        else cout << 1 << endl;
    }

    return 0;
}
accuracy: 1
time_ms: 170
memory_kb: 21860
final_rank: 14

code_snippet: #include <iostream>
#include <vector>
#include <stack>
#include <set>

using namespace std;

vector<vector<int>> G;
vector<int> seen;
vector<int> finished;
stack<int> cycle;


int DFS(int now, int parent, int cycleIndex){
    seen[now] = true;
    cycle.push(now);

    for (auto g: G[now]){
        // 逆流防止
        if (g == parent) continue;
        // 帰りがけ探索完了
        if (finished[g]) continue;

        // 帰りがけ探索が完了していないのに、２回目の訪問＝サイクルあり
        if (seen[g] && !finished[g]) return g;

        cycleIndex = DFS(g, now, cycleIndex);

        //サイクルを検知した時点で、探索を停止
        if (cycleIndex >= 0) return cycleIndex;
    }

    cycle.pop();
    finished[now] = true;
    return cycleIndex;
}

int main(){
    int N;
    cin >> N;
    
    G.assign(N, vector<int>());
    
    int u, v;
    for(int i=0; i<N; i++){
        cin >> u >> v;
        G[u-1].push_back(v-1);
        G[v-1].push_back(u-1);
    }

    seen.assign(N, false);
    finished.assign(N, false);

    int cycleIndex;
    for(int i=0; i<N; i++){
        cycleIndex = DFS(i, -1, -1);
    }
    
    set<int> cycleSet;
    while(!cycle.empty()){
        int n = cycle.top();
        cycle.pop();
        if (finished[n]) continue;
        cycleSet.insert(n);
        // if (n == cycleIndex) break;
    }

    int Q;
    cin >> Q;

    for (int i=0; i<Q; i++){
        int a, b;
        cin >> a >> b;
        a--;
        b--;
        if (cycleSet.count(a) && cycleSet.count(b)) cout << 2 << endl;
        else cout << 1 << endl;
    }

    return 0;
}
accuracy: 0.046511627906976744
time_ms: 60
memory_kb: 9312
final_rank: 20

code_snippet: #include <iostream>
#include <vector>
#include <iomanip>
#include <algorithm>
#include <tuple>
#include <set>
#include <map>
#include <bitset>
#include <cmath>
#include <deque>
#include <queue>
#include <stack>
#include <cassert>
#include <unordered_set>
#include <unordered_map>
#include <cmath>
using namespace std;
typedef long long ll;
#define rep(i, n) for (ll i = 0; i < (ll)(n); i++)
#define all(v) v.begin(), v.end()

ll llpow(ll a, ll t)
{
  ll res = 1;
  rep(i, t) res *= a;
  return res;
}

ll inf = std::numeric_limits<ll>::max();

vector<vector<ll>> g;
vector<bool> seen;
vector<bool> finished;
stack<ll> hist;
vector<ll> order;
ll pos = -1;

void dfs(ll u, ll p)
{
  seen[u] = true;
  hist.push(u); // サイクルのノードが蓄積
  rep(i, g[u].size())
  {
    ll v = g[u][i];
    if (v == p)
    {
      continue;
    }
    if (finished[v])
    {
      continue;
    }
    if (seen[v] && !finished[v]) // 探索中にループを抜ける前に親に到達してしまった：サイクル検知
    {
      pos = v; // サイクルの起点（一番親側）
      return;
    }
    dfs(v, u);
    if (pos != -1)
    {
      return;
    }
  }
  hist.pop(); // サイクルでなければ除かれる
  finished[u] = true;
}

int main()
{
  ll n;
  cin >> n;
  g.assign(n, {});
  seen.assign(n, false);
  finished.assign(n, false);
  rep(i, n)
  {
    ll a, b;
    cin >> a >> b;
    a--, b--;
    g[a].push_back(b);
    g[b].push_back(a);
  }
  rep(i, n)
  {
    sort(all(g[i]));
  }
  dfs(0, -1);

  set<ll> cycle;
  while (!hist.empty())
  {
    ll t = hist.top();
    cycle.insert(t);
    hist.pop();
    if (t == pos)
    {
      break;
    }
  }

  ll q;
  cin >> q;
  vector<ll> ans;
  rep(i, q)
  {
    ll a, b;
    cin >> a >> b;
    a--, b--;
    if (cycle.count(a) && cycle.count(b))
    {
      ans.push_back(2);
    }
    else
    {
      ans.push_back(1);
    }
  }
  rep(i, ans.size())
  {
    cout << ans[i] << endl;
  }
}
accuracy: 1
time_ms: 160
memory_kb: 23664
final_rank: 15

code_snippet: #include <bits/stdc++.h>
using namespace std;
using lli=long long int;
using ld=long double;
using vi=vector<int>;
using vvi=vector<vi>;
using vvvi=vector<vvi>;
using vvvvi=vector<vvvi>;
using vl=vector<lli>;
using vvl=vector<vl>;
using vb=vector<bool>;
using vvb=vector<vb>;
#define rep(i,s,e) for(int i=s;i<e;i++)
#define leap(i,s,e,j) for(int i=s;i<e;i+=j)
#define repl(i,s,e) for(lli i=s;i<e;i++)
#define rrep(i,s,e) for(int i=s-1;i>=e;i--)
#define rleap(i,s,e,j) for(int i=s-1;i>=e;i-=j)
#define in(v,seq) for(auto v:seq)
#define veci(v,s) vi v(s); rep(i,0,s) cin >> v.at(i);
#define vecl(v,s) vl v(s); rep(i,0,s) cin >> v.at(i);
#define all(s) s.begin(),s.end()
#define rall(s) s.rbegin(),s.rend()
using pii=pair<int,int>;
using pll=pair<lli,lli>;
#define mp(f,s) make_pair(f,s)
#define fi first
#define se second
using vpii=vector<pii>;
using vpll=vector<pll>;
#define vecpii(v,s) vpii v(s); rep(i,0,s) cin >> v.at(i).fi >> v.at(i).se;
#define vecpll(v,s) vpll v(s); rep(i,0,s) cin >> v.at(i).fi >> v.at(i).se;
#define pub(x) push_back(x)
#define puf(x) push_front(x)
#define pob(x) pop_back(x)
#define pof(x) pop_front(x)
#define emb(x) emplace_back(x)
#define print(s) cout << s << endl;
#define ptp(p) cout << p.fi << " " << p.se << endl;
const int I_INF=1<<30;
const lli LL_INF=1ll<<60;
const string alp="abcdefghijklmnopqrstuvwxyz";
const int let=alp.size(); // 26

using SGraph=vector<vector<int>>;

vector<bool> cycle(SGraph &G){
  int vertex=G.size();
  vector<bool> pre(vertex,false),post(vertex,false),ret(vertex,false);

  auto dfs=[&](auto &dfs,stack<int> &hist,int v,int pv)->int{
    pre.at(v)=true;
    hist.push(v);
    for(int nv:G.at(v)){
      if(nv==pv) continue;
      if(post.at(nv)) continue;

      if(pre.at(nv)) return nv;

      int p=dfs(dfs,hist,nv,v);
      if(p!=-1) return p;

    }
    
    post.at(v)=true;
    hist.pop();
    return -1;
  };

  for(int i=0;i<vertex;i++){
    stack<int> hist;
    int p=dfs(dfs,hist,i,-1);
    if(p!=-1){
      while(!hist.empty()){
        int u=hist.top();
        ret.at(u)=true;
        hist.pop();
        if(u==p) break;
      }
      return ret;
    }
  }
  return ret;
}

int main(){
  int vertex; cin >> vertex;
  SGraph G(vertex);
  rep(i,0,vertex){
    int u,v; cin >> u >> v;
    u--; v--;
    G[u].pub(v);
    G[v].pub(u);
  }

  auto c=cycle(G);
  
  int q; cin >> q;
  rep(i,0,q){
    int u,v; cin >> u >> v;
    u--; v--;
    if(c[u] && c[v]){
      print(2);
    }else{
      print(1);
    }
  }
}
accuracy: 1
time_ms: 120
memory_kb: 16848
final_rank: 7

code_snippet: #include <bits/stdc++.h>
#define ll long long
using namespace std;
int main() {
  int n; cin >> n;
  
  vector g(n + 5, vector<int>{});
  int has3 = 0;
  for (int i = 1; i <= n; ++i) {
    int u, v; cin >> u >> v;
    g[u].push_back(v), g[v].push_back(u);
    if ((int) g[u].size() >= 3) has3 = u;
    if ((int) g[v].size() >= 3) has3 = v;
  }
  vector<char> vis(n + 5), inloop(n + 5);
  auto dfs = [&](auto &&self, int u, int fa)->void {
    vis[u] = true;
    for (int v: g[u]) {
      if (v == fa) continue;
      if (vis[v]) has3 = v;
      else self(self, v, u);
    }
  } ;
  auto dfs2 = [&](auto &&self, int u, int fa)->bool {
    vis[u] = true;
    for (int v: g[u]) {
      if (v == fa) continue;
      if (vis[v]) inloop[u] = true;
      else inloop[u] |= self(self, v, u);
    }
    return inloop[u];
  } ;
  if (has3) {
    dfs(dfs, has3, 0);
    for (int i = 1; i <= n; ++i) vis[i] = false;
    dfs2(dfs2, has3, 0);
  }
  // for (int i = 1; i <= n; ++i) cerr << (int) i << " \n"[i == n];
  // for (int i = 1; i <= n; ++i) cerr << (int) inloop[i] << " \n"[i == n];
  int Q; cin >> Q;
  while (Q--) {
    int a, b; cin >> a >> b;
    if (!has3) {
      cout << 2 << '\n';
      continue;
    }
    if (inloop[a] && inloop[b]) cout << 2 << '\n';
    else cout << 1 << '\n';
  }

  return 0;
}
accuracy: 1
time_ms: 130
memory_kb: 16536
final_rank: 8

code_snippet: #include <bits/stdc++.h>
#define ll long long
using namespace std;
int main() {
  int n; cin >> n;
  
  vector g(n + 5, vector<int>{});
  int has3 = 0;
  for (int i = 1; i <= n; ++i) {
    int u, v; cin >> u >> v;
    g[u].push_back(v), g[v].push_back(u);
    if ((int) g[u].size() >= 3) has3 = u;
    if ((int) g[v].size() >= 3) has3 = v;
  }
  int Q; cin >> Q;
  vector<char> vis(n + 5), inloop(n + 5);
  auto dfs = [&](auto &&self, int u, int fa)->bool {
    vis[u] = true;
    for (int v: g[u]) {
      if (v == fa) continue;
      if (vis[v]) inloop[u] = true;
      else inloop[u] |= self(self, v, u);
    }
    return inloop[u];
  } ;
  if (has3) {
    dfs(dfs, has3, 0);
  }
  while (Q--) {
    int a, b; cin >> a >> b;
    if (!has3) {
      cout << 2 << '\n';
      continue;
    }
    if (inloop[a] && inloop[b]) cout << 2 << '\n';
    else cout << 1 << '\n';
  }

  return 0;
}
accuracy: 0.046511627906976744
time_ms: 60
memory_kb: 8360
final_rank: 18

code_snippet: #include<bits/stdc++.h>
using Graph = std::vector<std::vector<int>>;
int N, Q;
Graph G;
std::vector<bool> seen, finished;
std::stack<int> hits;
int pos = -1;
void dfs(int v, int p) {
    seen[v] = true;
    hits.push(v);
    for(auto &nv : G[v]) {
        if(nv == p) continue;

        if(finished[nv]) continue;
        else if(seen[nv]) {pos = nv; return;}

        dfs(nv, v);
        if(pos != -1) return;
    }
    hits.pop();
    finished[v] = true;
}

int main() {
    std::cin >> N;
    G = Graph(N+1);
    for(int i=0; i < N; i++) {
        int a, b;
        std::cin >> a >> b;
        G[a].push_back(b);
        G[b].push_back(a);
    }
    seen.assign(N+1, false);
    finished.assign(N+1, false);
    dfs(1, -1);
    std::set<int> cicle;
    while(!hits.empty()) {
        int v = hits.top();
        hits.pop();
        cicle.insert(v);
        if(v == pos) break;
    }
    int Q; std::cin >> Q;
    for(int i=0; i<Q; i++) {
        int a, b; std::cin >> a >> b;
        int ans = 1;
        if(cicle.count(a) && cicle.count(b)) ans = 2;
        std::cout << ans << std::endl;
    }
}
accuracy: 1
time_ms: 170
memory_kb: 22656
final_rank: 16

code_snippet: #include <bits/stdc++.h>


using namespace std;

//make -f ../makefile SRC=

/*
TODO:
hint:
N vertices with N edges => only 1 cycle max
whether v and w are in cycle
remove all of the Bridges ?
maybe useful
https://www.geeksforgeeks.org/print-all-the-cycles-in-an-undirected-graph/

guess:
start from leaf, remove connected vertices with deg == 2 (dfs)
*/


//------------------------------------------------------------------------------
bool DEBUG = false;
const int INF = 1000000000;

const int MAX_N = 100000;
static bool marked[MAX_N];
static bool in_cycle[MAX_N];
static int deg[MAX_N];

typedef vector<vector<int> > Graph;
//------------------------------------------------------------------------------
void dfs(int N, Graph& G, int v)
{
    if (marked[v] || deg[v] != 1) return;
    marked[v] = true;
    in_cycle[v] = false;

    for (int w: G[v])
    {
        if (marked[w]) continue;
        deg[v]--;
        deg[w]--;
        dfs(N, G, w);
    }
}

void init(int N, Graph& G)
{
    for (int v=0; v<N; ++v) { marked[v] = false; in_cycle[v] = true; }

    for (int v=0; v<N; ++v)
        if (deg[v] == 0)
            { marked[v] = true; in_cycle[v] = false; }

    for (int v=0; v<N; ++v)
        if (!marked[v] && deg[v] == 1)
            dfs(N, G, v);
}

void debug_graph(int N, Graph& G)
{
    printf("N=%d\nG:\n", N);

    for (int v=0; v<N; v++)
    {
        if (G[v].empty()) continue;
        printf("%d: ", v);
        for (int w: G[v])
            if (w > v)
                printf("%d ", w); 
        printf("\n");
    }

}

//------------------------------------------------------------------------------
int main()
{
    //DEBUG = true;
    //--------------------------------------------------------------------------
    int T, N, M, K, v, w, c, src, dest, num;
    //num = scanf("%d ", &T);
    //for (int t=1; t<=T; ++t)
    //{
        num = scanf("%d ", &N);
        Graph G(N);
        for (int v=0; v<N; ++v) deg[ v ] = 0;
        for (int m=0; m<N; ++m)
        {
            num = scanf("%d %d ", &v, &w);
            v--;
            w--;
            G[ v ].push_back( w );
            G[ w ].push_back( v );
            deg[ v ]++;
            deg[ w ]++;
        }
        init(N, G);

        num = scanf("%d ", &K);
        for (int k=0; k<K; ++k)
        {
            num = scanf("%d %d ", &v, &w);
            v--;
            w--;
            int res = ( in_cycle[v] && in_cycle[w] ? 2 : 1 );
            printf("%d\n", res);
        }
    //}
    //--------------------------------------------------------------------------
    return 0;
}
//------------------------------------------------------------------------------
accuracy: 1
time_ms: 30
memory_kb: 13952
final_rank: 1

code_snippet: #include <bits/stdc++.h>


using namespace std;

//make -f ../makefile SRC=

/*
TODO:
hint:
N vertices with N edges => only 1 cycle max
whether v and w are in cycle
remove all of the Bridges ?
maybe useful
https://www.geeksforgeeks.org/print-all-the-cycles-in-an-undirected-graph/

guess:
start from leaf, remove connected vertices with deg == 2 (dfs)
*/


//------------------------------------------------------------------------------
bool DEBUG = false;
const int INF = 1000000000;

const int MAX_N = 100000;
static bool marked[MAX_N];
static bool in_cycle[MAX_N];
static int deg[MAX_N];

typedef vector<vector<int> > Graph;
//------------------------------------------------------------------------------
void dfs(int N, Graph& G, int v)
{
    if (marked[v] || deg[v] > 2) return;
    marked[v] = true;
    in_cycle[v] = false;
    
    for (int w: G[v])
    {
        if (marked[w]) continue;
        dfs(N, G, w);
    }
}

//------------------------------------------------------------------------------
void init(int N, Graph& G)
{
    for (int v=0; v<N; ++v) { marked[v] = false; in_cycle[v] = true; }

    for (int v=0; v<N; ++v)
        if (!marked[v] && deg[v] == 1)
            dfs(N, G, v);
}

void debug_graph(int N, Graph& G)
{
    printf("N=%d\nG:\n", N);

    for (int v=0; v<N; v++)
    {
        if (G[v].empty()) continue;
        printf("%d: ", v);
        for (int w: G[v])
            if (w > v)
                printf("%d ", w); 
        printf("\n");
    }

}

//------------------------------------------------------------------------------
int main()
{
    //DEBUG = true;
    //--------------------------------------------------------------------------
    int T, N, M, K, v, w, c, src, dest, num;
    //num = scanf("%d ", &T);
    //for (int t=1; t<=T; ++t)
    //{
        num = scanf("%d ", &N);
        Graph G(N);
        for (int v=0; v<N; ++v) deg[ v ] = 0;
        for (int m=0; m<N; ++m)
        {
            num = scanf("%d %d ", &v, &w);
            v--;
            w--;
            G[ v ].push_back( w );
            G[ w ].push_back( v );
            deg[ v ]++;
            deg[ w ]++;
        }
        init(N, G);

        num = scanf("%d ", &K);
        for (int k=0; k<K; ++k)
        {
            num = scanf("%d %d ", &v, &w);
            v--;
            w--;
            int res = ( in_cycle[v] && in_cycle[w] ? 2 : 1 );
            printf("%d\n", res);
        }
    //}
    //--------------------------------------------------------------------------
    return 0;
}
//------------------------------------------------------------------------------
accuracy: 0.046511627906976744
time_ms: 20
memory_kb: 8412
final_rank: 17

code_snippet: #include<bits/stdc++.h>
#define _GLIBCXX_DEBUG
#define OVERLOAD_REP(v1, v2, v3, v4, NAME, ...) NAME
#define REP1(i, n) for (auto i = 0; (i) < (n); ++(i))
#define REP2(i, l, r) for (auto i = (l); (i) < (r); ++(i))
#define REP3(i, l, r, d) for (auto i = (l); (i) < (r); (i)+=(d))
#define rep(...) OVERLOAD_REP(__VA_ARGS__, REP3, REP2, REP1)(__VA_ARGS__)
#define OVERLOAD_PRE(v1, v2, v3, v4, NAME, ...) NAME
#define PRE1(i, n) for (auto i = (n)-1; (i) >= 0; --(i)) //[0,n)
#define PRE2(i, l, r) for (auto i = (r)-1; (i) >= (l); --(i)) //[l,r)
#define PRE3(i, l, r, d) for (auto i = (r)-1; (i) >= (l); (i)-=(d))
#define pre(...) OVERLOAD_PRE(__VA_ARGS__, PRE3, PRE2, PRE1)(__VA_ARGS__)
#define bg begin()
#define en end()
#define rbg rbegin()
#define ren rend()
#define all(x) x.bg,x.en
#define rall(x) x.rbg,x.ren
#define pb push_back
#define eb emplace_back
#define fir first
#define sec second
using namespace std;
using ll = long long;
using ull = unsigned long long;
using ld = long double;
using pii = pair<int,int>;
using pll = pair<ll,ll>;
using si = stack<int>;
using qi = queue<int>;
using qii = queue<pii>;
template<class t> using pql=priority_queue<t>;
template<class t> using pqg=priority_queue<t,vector<t>, greater<t>>;
template<class t> using vc=vector<t>;
template<class t> using vvc=vc<vc<t>>;
template<class t> using vvvc=vc<vc<vc<t>>>;
using vi=vc<int>;
using vvi=vc<vc<int>>;
using vll=vc<ll>;
using vvll=vc<vc<ll>>;
using vd=vc<double>;
using vvd=vc<vc<double>>;
using vb=vc<bool>;
using vvb=vc<vc<bool>>;
using vch=vc<char>;
using vs=vc<string>;
const int inf = 1073741823;
const ll infl = 1LL << 60;
const double infd = 1e18;
const ll mod = 1000000007;
template<class t,class u> bool chmax(t&a,u b){if(a<b){a=b; return true;} return false;}
template<class t,class u> bool chmin(t&a,u b){if(a>b){a=b; return true;} return false;}
void yes(){ cout << "Yes\n"; }
void no(){ cout << "No\n";}

int main(){
	ios::sync_with_stdio(false);
  	cin.tie(0);
	int n; cin >> n;
	vvi g(n,vi());
	vi deg(n);
	rep(i,n){
		int u,v; cin >> u >> v;
		u--; v--;
		g[u].pb(v);
		g[v].pb(u);
		deg[u]++;
		deg[v]++;
	}

	vb seen(n);
	qi q;
	rep(i,n)if(deg[i]==1){
		q.push(i);
	}

	while(!q.empty()){
		int v=q.front(); q.pop();
		seen[v]=true;
		deg[v]--;
		for(auto &u:g[v]){
			if(--deg[u]==1) q.push(u);
		}
	}

	int Q; cin >> Q;
	rep(i,Q){
		int a,b; cin >> a >> b;
		a--; b--;
		if(!seen[a]&&!seen[b])cout << 2 << endl;
		else cout << 1 << endl;
	}
	return 0;
}
accuracy: 1
time_ms: 80
memory_kb: 8892
final_rank: 2

code_snippet: // #include <bits/stdc++.h>
// #include "graph/graph_template.hpp"
// #include "graph/functional_graph_cycle_detection.hpp"
// using namespace std;
// typedef long long int ll;
// #define rep(i, N) for(ll i = 0; i < (ll)N; i++)
// 
// template<class T> inline bool chmax(T& a, T b) {
//     if (a < b) {
//         a = b;
//         return true;
//     }
//     return false;
// }
// 
// int main() {
//     ll N; cin >> N;
//     Graph<ll> graph(N);
//     rep (i, N) {
//         ll a, b; cin >> a >> b; a--; b--;
//         graph[a].push_back(b);
//         graph[b].push_back(a);
//     }
//     FunctionalGraphCycleDetection<ll> fg(graph, false);
//     ll Q; cin >> Q;
//     rep (i, Q) {
//         ll a, b; cin >> a >> b; a--; b--;
//         if (fg.in_cycle[a] && fg.in_cycle[b]) cout << 2 << endl;
//         else cout << 1 << endl;
//     }
// 
//     return 0;
// }
#include <bits/stdc++.h>

/**
 * @brief グラフテンプレート
 */
template <class T>
struct Edge {
    int from;
    int to;
    T cost;

    Edge(int from = -1, int to = -1, T cost = -1)
        : from(from), to(to), cost(cost) {}
};

template <class T>
struct Graph {
    int n;
    std::vector<std::vector<T>> graph;

    Graph(int n) : n(n), graph(n, std::vector<T>()) {}
    inline std::vector<T>& operator[](int i) { return graph[i]; }
    size_t size() const { return graph.size(); }

    std::vector<int> preorder, postorder;

    /**
     * @brief 行きがけ順、帰りがけ順の配列を作る
     */
    void calculateOrder() {
        std::vector<bool> reached(n, false);
        auto dfs = [&](auto f, int v, int p) -> void {
            if (reached[v]) return;
            reached[v] = true;
            preorder.push_back(v);
            for (auto c : graph[v]) {
                if (c == p) continue;
                f(f, c, v);
            }
            postorder.push_back(v);
            return;
        };

        for (int i = 0; i < n; i++)
            if (!reached[i]) dfs(dfs, i, -1);

        assert((int)(preorder.size()) == n);
        assert((int)(postorder.size()) == n);
    }
};

/**
 * @brief Functional Graph Cycle Detection (Functional Graphのサイクル検出)
 */
template <class T>
struct FunctionalGraphCycleDetection {
    int n;
    bool is_directed;
    Graph<T> graph;
    std::vector<bool> reached, finished, in_cycle;
    std::vector<T> history;

    FunctionalGraphCycleDetection(Graph<T>& graph, bool is_directed = true)
        : n((int)(graph.size())),
          is_directed(is_directed),
          graph(graph),
          reached(n, false),
          finished(n, false),
          in_cycle(n, true) {
        if (is_directed)
            for (int i = 0; i < n; i++) assert((int)(graph[i].size()) == 1);
        build();
    }

    /**
     * @brief in_cycleを構築する
     */
    void build() {
        std::queue<int> que;
        std::vector<int> deg(n, 0);
        int target = !is_directed;
        for (int i = 0; i < n; i++)
            for (auto c : graph[i]) deg[c]++;
        for (int i = 0; i < n; i++) {
            if (deg[i] == target) {
                que.push(i);
                in_cycle[i] = false;
            }
        }
        while (!que.empty()) {
            auto v = que.front();
            que.pop();
            for (auto c : graph[v]) {
                if (!in_cycle[c]) continue;
                deg[c]--;
                if (deg[c] == target) {
                    in_cycle[c] = false;
                    que.push(c);
                }
            }
        }
        return;
    }

    /**
     * @brief 頂点posからサイクルを構築
     */
    std::vector<T> reconstruct(int pos) {
        std::vector<T> cycle;
        int v = pos;
        int parent = -1;
        do {
            cycle.push_back(v);
            reached[v] = true;
            for (auto c : graph[v]) {
                if (c == parent) continue;
                if (!in_cycle[c]) continue;
                v = c;
                parent = v;
                break;
            }
        } while (v != pos);
        return cycle;
    }

    /**
     * @brief 全てのサイクルを列挙
     */
    std::vector<std::vector<T>> detect_all() {
        std::vector<std::vector<T>> res;
        for (int v = 0; v < (int)(graph.size()); v++) {
            if (!in_cycle[v] || reached[v]) continue;
            std::vector<T> cycle = reconstruct(v);
            if (!cycle.empty())
                res.push_back(cycle);
            else
                assert(false);
        }
        return res;
    }
};
using namespace std;
typedef long long int ll;
#define rep(i, N) for (ll i = 0; i < (ll)N; i++)

template <class T>
inline bool chmax(T& a, T b) {
    if (a < b) {
        a = b;
        return true;
    }
    return false;
}

int main() {
    ll N;
    cin >> N;
    Graph<ll> graph(N);
    rep(i, N) {
        ll a, b;
        cin >> a >> b;
        a--;
        b--;
        graph[a].push_back(b);
        graph[b].push_back(a);
    }
    FunctionalGraphCycleDetection<ll> fg(graph, false);
    ll Q;
    cin >> Q;
    rep(i, Q) {
        ll a, b;
        cin >> a >> b;
        a--;
        b--;
        if (fg.in_cycle[a] && fg.in_cycle[b])
            cout << 2 << endl;
        else
            cout << 1 << endl;
    }

    return 0;
}
accuracy: 1
time_ms: 130
memory_kb: 14432
final_rank: 6

code_snippet: #include <iostream>
#include <queue>
#include <vector>

using namespace std;
#define rep(i, n) for(int i=0; i<n; i++)

using Graph = vector<vector<int>>;

int main() {
    int N; cin >> N;
    Graph G(N);
    vector<int> deg(N, 0);
    rep(_, N) {
        int a, b; cin >> a >> b;
        a--; b--;
        G[a].push_back(b);
        G[b].push_back(a);
        deg[a]++; deg[b]++;
    }
    queue<int> q;
    rep(i, N) if(deg[i]==1) q.push(i);

    vector<bool> NoPushed(N, true);
    while(!q.empty()) {
        int v = q.front(); q.pop();
        NoPushed[v] = false;
        for(auto next : G[v]) {
            deg[next]--;
            if(deg[next]==1) q.push(next);
        }
    }
    int Q; cin >> Q;
    rep(_, Q) {
        int a, b; cin >> a >> b;
        a--; b--;
        if(NoPushed[a] && NoPushed[b]) cout << 2 << endl;
        else cout << 1 << endl;
    }
}
accuracy: 1
time_ms: 130
memory_kb: 9088
final_rank: 4

code_snippet: #include <iostream>
#include <vector>
#include <stack>
#include <set>

using namespace std;
#define rep(i, n) for(int i=0; i<n; i++)

using Graph = vector<vector<int>>;

Graph G;
vector<bool> visited, finished;
int now=-1;
stack<int> histry;

void dfs(int v, int from) {
    visited[v] = true;
    histry.push(v);
    for (int next : G[v]) {
        if(next==from || finished[next]) continue;
        if(visited[next] && !finished[next]) {
            now = next;
            return;
        }
        dfs(next, v);
        if(now != -1) return;
    }
    histry.pop();
    finished[v] = true;
}

int main() {
    int N; cin >> N;
    G.resize(N); visited.resize(N, false); finished.resize(N, false);
    rep(i, N) {
        int u, v; cin >> u >> v;
        u--;v--;
        G[u].push_back(v); G[v].push_back(u);
    }

    dfs(0, -1);
    set<int> cycle;
    while(!histry.empty()) {
        int t = histry.top(); histry.pop();
        cycle.insert(t);
        if(t == now) break;
    }

    int Q; cin >> Q;
    rep(i,Q) {
        int a, b; cin >> a >> b;
        a--;b--;
        if(cycle.count(a) && cycle.count(b))
            cout << 2 << endl;
        else
            cout << 1 << endl;
    }
}
accuracy: 1
time_ms: 160
memory_kb: 22568
final_rank: 13

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
using Graph = vector<vector<int>>;
using Grid = vector<vector<int>>;
// #include <atcoder/all>
// using namespace atcoder;
// https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2891

vector<bool> seen;
vector<bool> finished;
int pos = -1;
vector<int> hist;

void dfs(Graph &G, int v, int p) {
    seen[v] = true;
    hist.push_back(v);
    for (int next : G[v]) {
        if (next == p) {
            continue;
        }
        else if (finished[next]) {
            continue;
        }
        else if (seen[next] && !finished[next]) {
            // 閉路発見
            pos = next;
            return;
        }
        dfs(G, next, v);
        if (pos != -1) {
            return;
        }
    }
    hist.pop_back();
    finished[v] = true;
}

int main() {
    int N;
    cin >> N;
    Graph G(N);
    for (int i = 0; i < N; i++) {
        int u, v;
        cin >> u >> v;
        u--; v--;
        G[u].push_back(v);
        G[v].push_back(u);
    }
    seen.assign(N, false);
    finished.assign(N, false);
    dfs(G, 0, -1);
    set<int> cicle;
    while (!hist.empty()) {
        int t = hist.back();
        cicle.insert(t);
        hist.pop_back();
        if (t == pos) {
            break;
        }
    }

    int Q;
    cin >> Q;
    for (int i = 0; i < Q; i++) {
        int a, b;
        cin >> a >> b;
        a--; b--;
        // 処理
        int count = (cicle.count(a) + cicle.count(b) == 2 ? 2 : 1);
        cout << count << endl;
    }
}
accuracy: 1
time_ms: 180
memory_kb: 19684
final_rank: 12

code_snippet: #line 1 "main.cpp"
#include <iostream>

#line 2 "/Users/gyouzasushi/kyopro/library/graph/functional_graph.hpp"

#include <algorithm>
#include <vector>
struct functional_graph {
public:
    functional_graph(int n) : _n(n), graph(n) {
    }
    void add_edge(int u, int v) {
        graph[u].push_back(v);
        graph[v].push_back(u);
    }
    void add_directed_edge(int from, int to) {
        graph[from].push_back(to);
    }
    std::vector<int> loop() {
        std::vector<int> path;
        std::vector<int> check(_n, 0);
        auto dfs = [&](auto dfs, int u, int p) -> int {
            check[u]++;
            path.push_back(u);
            for (int v : graph[u]) {
                if (v == p) continue;
                if (check[v] == 0) {
                    int ret = dfs(dfs, v, u);
                    if (ret != -1) return ret;
                } else if (check[v] == 1) {
                    return v;
                }
            }
            path.pop_back();
            check[u]++;
            return -1;
        };
        std::vector<int>::iterator it =
            std::find(path.begin(), path.end(), dfs(dfs, 0, -1));
        return std::vector(it, path.end());
    }
    std::vector<std::vector<std::pair<int, int>>> tree() {
        std::vector<int> _loop = loop();
        std::vector<std::vector<std::pair<int, int>>> ret(_loop.size());
        int k = _loop.size();
        for (int i = 0; i < k; i++) {
            auto dfs = [&](auto dfs, int u, int p) -> void {
                for (int v : graph[u]) {
                    if (v == p) continue;
                    if (v == _loop[i + 1 == k ? 0 : i + 1]) continue;
                    if (v == _loop[i == 0 ? k - 1 : i - 1]) continue;
                    ret[i].emplace_back(u, v);
                    dfs(dfs, v, u);
                }
            };
            dfs(dfs, _loop[i], -1);
        }
        return ret;
    }

private:
    int _n;
    std::vector<std::vector<int>> graph;
};
#line 4 "main.cpp"
int main() {
    int n;
    std::cin >> n;
    functional_graph g(n);
    for (int i = 0; i < n; i++) {
        int u, v;
        std::cin >> u >> v;
        g.add_edge(--u, --v);
    }
    std::vector loop = g.loop();
    std::vector in_loop(n, false);
    for (int u : loop) {
        in_loop[u] = true;
    }
    int q;
    std::cin >> q;
    while (q--) {
        int a, b;
        std::cin >> a >> b;
        a--, b--;
        if (in_loop[a] && in_loop[b]) {
            std::cout << 2 << '\n';
        } else {
            std::cout << 1 << '\n';
        }
    }
}
accuracy: 1
time_ms: 130
memory_kb: 19200
final_rank: 10

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define rep(i,j,k) for(long long i=j;i<=k;i++)
using ll= long long int;
using vi=vector<int>;
using vii=vector<vector<int>>;
using vl=vector<ll>;
using vd=vector<double>;
using vb=vector<bool>;

vector<vector<int>> G(100005);
vector<int> p(100005);
vector<bool> flag(100005);

int main() {ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
	int n; cin >> n;
	rep(i, 1, n){
		int a, b;
		cin >> a >> b;
		G[a].push_back(b);
		G[b].push_back(a);
		p[a] ++;
		p[b] ++;
	}
	
	queue<int> notring;
	queue<int> que;
	rep(i, 1, n){
		if(p[i] != 1) continue;
		notring.push(i);
		que.push(i);
	}
	
	while(!que.empty()){
		int now = que.front();
		que.pop();
		p[now] = 0;
		for(int x : G[now]){
			p[x] --;
			if(p[x] == 1){
				que.push(x);
				notring.push(x);
			}
		}
	}
	
	while(!notring.empty()){
		int tmp = notring.front();
		notring.pop();
		flag[tmp] = 1;
	}
	
	int q; cin >> q;
	while(q--){
		int a,b;
		cin >> a >> b;
		if(flag[a] == 0 && flag[b] == 0) cout << 2 << endl;
		else cout << 1 << endl;
	}
}
accuracy: 1
time_ms: 80
memory_kb: 9444
final_rank: 3

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define rep(i,j,k) for(long long i=j;i<=k;i++)
using ll= long long int;
using vi=vector<int>;
using vii=vector<vector<int>>;
using vl=vector<ll>;
using vd=vector<double>;
using vb=vector<bool>;

vii G(100005);
stack<int> cycle;

vb seen(100005,0);
bool f = 0;

void dfs(int k, int from){
	seen[k] = 1;
	for(int next : G[k]){
		if(next == from) continue;
		cycle.push(next);
		if(seen[next]){
			f = 1;
			return;
		}
		dfs(next, k);
		if(f) return;
		cycle.pop();
	}
}
vb flag(100005);

int main() {ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
	int n,q; cin >> n;
	rep(i, 1, n){
		int u,v;
		cin >> u >> v;
		G[u].push_back(v);
		G[v].push_back(u);
	}
	
	cycle.push(1);
	dfs(1, 1);
	int start = cycle.top();
	cycle.pop();
	while(1){
		int tmp = cycle.top();
		flag[tmp] = 1;
		cycle.pop();
		if(tmp == start) break;
	}
	
	cin >> q;
	while(q--){
		int a, b; cin >> a >> b;
		if(flag[a] && flag[b]) cout << 2 << endl;
		else cout << 1 << endl;
	}
	return 0;
}
accuracy: 1
time_ms: 90
memory_kb: 16812
final_rank: 5

code_snippet: #line 1 "/opt/library/template.hpp"
#include <bits/stdc++.h>
using namespace std;

using ll = long long;
using i64 = long long;
using u32 = unsigned int;
using u64 = unsigned long long;
using i128 = __int128;
using u128 = unsigned __int128;
using f128 = __float128;

template <class T>
constexpr T infty = 0;
template <>
constexpr int infty<int> = 1'000'001'000;
template <>
constexpr ll infty<ll> = ll(infty<int>) * infty<int> * 2;
template <>
constexpr u32 infty<u32> = infty<int>;
template <>
constexpr u64 infty<u64> = infty<ll>;
template <>
constexpr i128 infty<i128> = i128(infty<ll>) * infty<ll>;
template <>
constexpr double infty<double> = infty<ll>;
template <>
constexpr long double infty<long double> = infty<ll>;
#define inf infty<ll>

using pi = pair<ll, ll>;
using vi = vector<ll>;
using vvi = vector<vector<ll>>;
template <class T>
using vc = vector<T>;
template <class T>
using vvc = vector<vc<T>>;
template <class T>
using vvvc = vector<vvc<T>>;
template <class T>
using vvvvc = vector<vvvc<T>>;
template <class T>
using vvvvvc = vector<vvvvc<T>>;
template <class T>
using pq = priority_queue<T>;
template <class T>
using pqg = priority_queue<T, vector<T>, greater<T>>;

#define vv(type, name, h, ...) \
  vector<vector<type>> name(h, vector<type>(__VA_ARGS__))
#define vvv(type, name, h, w, ...)   \
  vector<vector<vector<type>>> name( \
      h, vector<vector<type>>(w, vector<type>(__VA_ARGS__)))
#define vvvv(type, name, a, b, c, ...)       \
  vector<vector<vector<vector<type>>>> name( \
      a, vector<vector<vector<type>>>(       \
             b, vector<vector<type>>(c, vector<type>(__VA_ARGS__))))

#define rep1(a) for (ll _ = 0; _ < (ll)(a); ++_)
#define rep2(i, a) for (ll i = 0; i < (ll)(a); ++i)
#define rep3(i, a, b) for (ll i = a; i < (ll)(b); ++i)
#define rep4(i, a, b, c) for (ll i = a; i < (ll)(b); i += (c))
#define rrep1(a) for (ll i = (a)-1; i >= (ll)(0); --i)
#define rrep2(i, a) for (ll i = (a)-1; i >= (ll)(0); --i)
#define rrep3(i, a, b) for (ll i = (b)-1; i >= (ll)(a); --i)
#define rrep4(i, a, b, c) for (ll i = (b)-1; i >= (ll)(a); i -= (c))
#define overload4(a, b, c, d, e, ...) e
#define rep(...) overload4(__VA_ARGS__, rep4, rep3, rep2, rep1)(__VA_ARGS__)
#define rrep(...) overload4(__VA_ARGS__, rrep4, rrep3, rrep2, rrep1)(__VA_ARGS__)

#define all(x) (x).begin(),(x).end()
#define len(x) (ll)(x.size())
#define elif else if
#define bit(x, i) (((x)>>(i))&1)

#define eb emplace_back
#define mp make_pair
#define mt make_tuple
#define fi first
#define se second

#define stoi stoll
#define abs llabs

#define MIN(v) *min_element(all(v))
#define MAX(v) *max_element(all(v))
#define LB(c, x) distance((c).begin(), lower_bound(all(c), (x)))
#define UB(c, x) distance((c).begin(), upper_bound(all(c), (x)))
#define UNIQUE(x) \
  sort(all(x)), x.erase(unique(all(x)), x.end()), x.shrink_to_fit()

ll popcnt(ll x) { return __builtin_popcountll(x); }
ll popcnt(u64 x) { return __builtin_popcountll(x); }
ll popcnt_mod_2(ll x) { return __builtin_parityll(x); }
ll popcnt_mod_2(u64 x) { return __builtin_parityll(x); }
ll topbit(ll x) { return (x == 0 ? -1 : 63 - __builtin_clzll(x)); }
ll topbit(u64 x) { return (x == 0 ? -1 : 63 - __builtin_clzll(x)); }
ll lowbit(ll x) { return (x == 0 ? -1 : __builtin_ctzll(x)); }
ll lowbit(u64 x) { return (x == 0 ? -1 : __builtin_ctzll(x)); }

template <typename T>
T floor(T a, T b) {
  return a / b - (a % b && (a ^ b) < 0);
}
template <typename T>
T ceil(T x, T y) {
  return floor(x + y - 1, y);
}
template <typename T>
T bmod(T x, T y) {
  return x - y * floor(x, y);
}
template <typename T>
pair<T, T> divmod(T x, T y) {
  T q = floor(x, y);
  return {q, x - q * y};
}

template<typename T> T SUM(const vector<T> &A) {
  T s = 0; for (auto &&a: A) s += a;
  return s;
}

template <typename T>
T POP(queue<T> &que) {
  T a = que.front();
  que.pop();
  return a;
}
template <typename T>
T POP(deque<T> &que) {
  T a = que.front();
  que.pop_front();
  return a;
}
template <typename T>
T POP(pq<T> &que) {
  T a = que.top();
  que.pop();
  return a;
}
template <typename T>
T POP(pqg<T> &que) {
  T a = que.top();
  que.pop();
  return a;
}
template <typename T>
T POP(vc<T> &que) {
  T a = que.back();
  que.pop_back();
  return a;
}

template <typename F>
ll binary_search(F check, ll ok, ll ng, bool check_ok = true) {
  if (check_ok) assert(check(ok));
  while (abs(ok - ng) > 1) {
    auto x = (ng + ok) / 2;
    (check(x) ? ok : ng) = x;
  }
  return ok;
}
template <typename F>
f128 binary_search_real(F check, f128 ok, f128 ng, ll iter = 100) {
  rep(iter) {
    f128 x = (ok + ng) / 2;
    (check(x) ? ok : ng) = x;
  }
  return (ok + ng) / 2;
}

// ? は -1
vc<int> s_to_vi(const string &S, char first_char) {
  vc<int> A(S.size());
  rep(i, S.size()) { A[i] = (S[i] != '?' ? S[i] - first_char : -1); }
  return A;
}

template <typename T, typename U>
vc<T> cumsum(vc<U> &A, ll off = 1) {
  ll N = A.size();
  vc<T> B(N + 1);
  rep(i, N) { B[i + 1] = B[i] + A[i]; }
  if (off == 0) B.erase(B.begin());
  return B;
}

// stable sort
template <typename T>
vi argsort(const vector<T> &A) {
  vi ids(len(A));
  iota(all(ids), 0);
  sort(all(ids),
       [&](ll i, ll j) { return (A[i] == A[j] ? i < j : A[i] < A[j]); });
  return ids;
}

// A[I[0]], A[I[1]], ...
template <typename T>
vc<T> rearrange(const vc<T> &A, const vi &I) {
  vc<T> B(len(I));
  rep(i, len(I)) B[i] = A[I[i]];
  return B;
}

template<typename T> inline bool chmax(T &a, T b) {return ((a<b)?(a=b,true):(false));}
template<typename T> inline bool chmin(T &a, T b) {return ((a>b)?(a=b,true):(false));}

inline void wt(const char c) { cout << c; }
inline void wt(const string s) { cout << s; }
inline void wt(const char *s) { cout << s; }

template <typename T>
void wt_integer(T x) {
  cout << (x);
}
template <typename T>
void wt_real(T x) {
  cout << fixed << setprecision(15) << (long double)(x);
}
template <typename T>
void wt_integer128(T x) {
  char buf[64];
  char *d = end(buf);
  d--; *d = '\0';
  __uint128_t tmp = ((x < 0)? -x : x);
  do {
    d--; *d = char(tmp%10 + '0'); tmp /= 10;
  } while (tmp);
  if (x < 0) {
    d--; *d = '-';
  }
  cout << d;
}

inline void wt(int x) { wt_integer(x); }
inline void wt(ll x) { wt_integer(x); }
inline void wt(i128 x) { wt_integer128(x); }
inline void wt(u32 x) { wt_integer(x); }
inline void wt(u64 x) { wt_integer(x); }
inline void wt(u128 x) { wt_integer128(x); }
inline void wt(double x) { wt_real(x); }
inline void wt(long double x) { wt_real(x); }
inline void wt(f128 x) { wt_real(x); }

template <class T, class U>
void wt(const pair<T, U> val) {
  wt(val.first); wt(' '); wt(val.second);
}
template <size_t N = 0, typename T>
void wt_tuple(const T t) {
  if constexpr (N < std::tuple_size<T>::value) {
    if constexpr (N > 0) { wt(' '); }
    const auto x = std::get<N>(t);
    wt(x);
    wt_tuple<N + 1>(t);
  }
}
template <class... T>
void wt(tuple<T...> tpl) {
  wt_tuple(tpl);
}
template <class T, size_t S>
void wt(const array<T, S> val) {
  auto n = val.size();
  for (size_t i = 0; i < n; i++) {
    if (i) wt(' ');
    wt(val[i]);
  }
}
template <class T>
void wt(const vector<T> val) {
  auto n = val.size();
  for (size_t i = 0; i < n; i++) {
    if (i) wt(' ');
    wt(val[i]);
  }
}

void print() { wt('\n'); }
template <class Head, class... Tail>
void print(Head &&head, Tail &&... tail) {
  wt(head);
  if (sizeof...(Tail)) wt(' ');
  print(forward<Tail>(tail)...);
}

void YES(bool t = 1) { print(t ? "YES" : "NO"); }
void NO(bool t = 1) { YES(!t); }
void Yes(bool t = 1) { print(t ? "Yes" : "No"); }
void No(bool t = 1) { Yes(!t); }
void yes(bool t = 1) { print(t ? "yes" : "no"); }
void no(bool t = 1) { yes(!t); }
void onez(bool t = 1) { print(t ? 1 : 0); }
#define endl '\n'
#define dump(x) {cerr << #x " = " << x << '\n';}
#line 2 "/opt/library/graph/base.hpp"

template <typename T>
struct Edge {
  ll frm, to;
  T cost;
  ll id;
};

template <typename T = ll, bool directed = false>
struct Graph {
  static constexpr bool is_directed = directed;
  ll N, M;
  using cost_type = T;
  using edge_type = Edge<T>;
  vector<edge_type> edges;
  vi indptr;
  vc<edge_type> csr_edges;
  vc<ll> vc_deg, vc_indeg, vc_outdeg;
  bool prepared;

  class OutgoingEdges {
  public:
    OutgoingEdges(const Graph* G, ll l, ll r) : G(G), l(l), r(r) {}

    const edge_type* begin() const {
      if (l == r) { return 0; }
      return &G->csr_edges[l];
    }

    const edge_type* end() const {
      if (l == r) { return 0; }
      return &G->csr_edges[r];
    }

  private:
    const Graph* G;
    ll l, r;
  };

  bool is_prepared() { return prepared; }

  Graph() : N(0), M(0), prepared(0) {}
  Graph(ll N) : N(N), M(0), prepared(0) {}

  void build(ll n) {
    N = n, M = 0;
    prepared = 0;
    edges.clear();
    indptr.clear();
    csr_edges.clear();
    vc_deg.clear();
    vc_indeg.clear();
    vc_outdeg.clear();
  }

  void add(ll frm, ll to, T cost = 1, ll i = -1) {
    assert(!prepared);
    assert(0 <= frm && 0 <= to && to < N);
    if (i == -1) i = M;
    auto e = edge_type({frm, to, cost, i});
    edges.eb(e);
    ++M;
  }

#ifdef FASTIO
  // wt, off
  void read_tree(bool wt = false, ll off = 1) { read_graph(N - 1, wt, off); }

  void read_graph(ll M, bool wt = false, ll off = 1) {
    for (ll m = 0; m < M; ++m) {
      LL(a, b);
      a -= off, b -= off;
      if (!wt) {
        add(a, b);
      } else {
        T c;
        read(c);
        add(a, b, c);
      }
    }
    build();
  }
#endif

  void build() {
    assert(!prepared);
    prepared = true;
    indptr.assign(N + 1, 0);
    for (auto&& e: edges) {
      indptr[e.frm + 1]++;
      if (!directed) indptr[e.to + 1]++;
    }
    for (ll v = 0; v < N; ++v) { indptr[v + 1] += indptr[v]; }
    auto counter = indptr;
    csr_edges.resize(indptr.back() + 1);
    for (auto&& e: edges) {
      csr_edges[counter[e.frm]++] = e;
      if (!directed)
        csr_edges[counter[e.to]++] = edge_type({e.to, e.frm, e.cost, e.id});
    }
  }

  OutgoingEdges operator[](ll v) const {
    assert(prepared);
    return {this, indptr[v], indptr[v + 1]};
  }

  vi deg_array() {
    if (vc_deg.empty()) calc_deg();
    return vc_deg;
  }

  pair<vi, vi> deg_array_inout() {
    if (vc_indeg.empty()) calc_deg_inout();
    return {vc_indeg, vc_outdeg};
  }

  ll deg(ll v) {
    if (vc_deg.empty()) calc_deg();
    return vc_deg[v];
  }

  ll in_deg(ll v) {
    if (vc_indeg.empty()) calc_deg_inout();
    return vc_indeg[v];
  }

  ll out_deg(ll v) {
    if (vc_outdeg.empty()) calc_deg_inout();
    return vc_outdeg[v];
  }

#ifdef FASTIO
  void debug() {
    print("Graph");
    if (!prepared) {
      print("frm to cost id");
      for (auto&& e: edges) print(e.frm, e.to, e.cost, e.id);
    } else {
      print("indptr", indptr);
      print("frm to cost id");
      rep(v, N) for (auto&& e: (*this)[v]) print(e.frm, e.to, e.cost, e.id);
    }
  }
#endif

  vi new_idx;
  vc<bool> used_e;

  // G における頂点 V[i] が、新しいグラフで i になるようにする
  // {G, es}
  Graph<T, directed> rearrange(vi V, bool keep_eid = 0) {
    if (len(new_idx) != N) new_idx.assign(N, -1);
    if (len(used_e) != M) used_e.assign(M, 0);
    ll n = len(V);
    rep(i, n) new_idx[V[i]] = i;
    Graph<T, directed> G(n);
    vi history;
    rep(i, n) {
      for (auto&& e: (*this)[V[i]]) {
        if (used_e[e.id]) continue;
        ll a = e.frm, b = e.to;
        if (new_idx[a] != -1 && new_idx[b] != -1) {
          history.eb(e.id);
          used_e[e.id] = 1;
          ll eid = (keep_eid ? e.id : -1);
          G.add(new_idx[a], new_idx[b], e.cost, eid);
        }
      }
    }
    rep(i, n) new_idx[V[i]] = -1;
    for (auto&& eid: history) used_e[eid] = 0;
    G.build();
    return G;
  }

private:
  void calc_deg() {
    assert(vc_deg.empty());
    vc_deg.resize(N);
    for (auto&& e: edges) vc_deg[e.frm]++, vc_deg[e.to]++;
  }

  void calc_deg_inout() {
    assert(vc_indeg.empty());
    vc_indeg.resize(N);
    vc_outdeg.resize(N);
    for (auto&& e: edges) { vc_indeg[e.to]++, vc_outdeg[e.frm]++; }
  }
};
#line 3 "main.cpp"

int solve();
int main() {
  cin.tie(nullptr);
  ios_base::sync_with_stdio(false);
  while (!solve()) {break;}
  return 0;
}

int solve() {
  ll N, Q, u, v, a, b;
  cin >> N;
  Graph<ll> G(N);
  rep(N) {
    cin >> u >> v;
    u--; v--;
    G.add(u, v);
  }
  G.build();

  ll pos = -1;
  vc<bool> seen(N, false), finished(N, false);
  stack<ll> hst;
  auto dfs = [&](auto self, ll v, ll p) -> void {
    seen[v] = true;
    hst.push(v);
    for (auto e: G[v]) {
      if (e.to == p) continue;
      if (finished[e.to]) continue;
      if (seen[e.to] and !finished[e.to]) {
        pos = e.to;
        return;
      }
      self(self, e.to, v);
      if (pos != -1) return;
    }
    hst.pop();
    finished[v] = true;
  };
  dfs(dfs, 0, -1);

  set<ll> cycle;
  while (!hst.empty()) {
    ll t = hst.top(); hst.pop();
    cycle.emplace(t);
    if (t == pos) break;
  }

  cin >> Q;
  rep(Q) {
    cin >> a >> b;
    a--; b--;
    if (cycle.count(a) and cycle.count(b)) print(2);
    else print(1);
  }
  return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 29668
final_rank: 9

code_snippet: #line 1 "/opt/library/template.hpp"
#include <bits/stdc++.h>
using namespace std;

using ll = long long;
using i64 = long long;
using u32 = unsigned int;
using u64 = unsigned long long;
using i128 = __int128;
using u128 = unsigned __int128;
using f128 = __float128;

template <class T>
constexpr T infty = 0;
template <>
constexpr int infty<int> = 1'000'001'000;
template <>
constexpr ll infty<ll> = ll(infty<int>) * infty<int> * 2;
template <>
constexpr u32 infty<u32> = infty<int>;
template <>
constexpr u64 infty<u64> = infty<ll>;
template <>
constexpr i128 infty<i128> = i128(infty<ll>) * infty<ll>;
template <>
constexpr double infty<double> = infty<ll>;
template <>
constexpr long double infty<long double> = infty<ll>;
#define inf infty<ll>

using pi = pair<ll, ll>;
using vi = vector<ll>;
using vvi = vector<vector<ll>>;
template <class T>
using vc = vector<T>;
template <class T>
using vvc = vector<vc<T>>;
template <class T>
using vvvc = vector<vvc<T>>;
template <class T>
using vvvvc = vector<vvvc<T>>;
template <class T>
using vvvvvc = vector<vvvvc<T>>;
template <class T>
using pq = priority_queue<T>;
template <class T>
using pqg = priority_queue<T, vector<T>, greater<T>>;

#define vv(type, name, h, ...) \
  vector<vector<type>> name(h, vector<type>(__VA_ARGS__))
#define vvv(type, name, h, w, ...)   \
  vector<vector<vector<type>>> name( \
      h, vector<vector<type>>(w, vector<type>(__VA_ARGS__)))
#define vvvv(type, name, a, b, c, ...)       \
  vector<vector<vector<vector<type>>>> name( \
      a, vector<vector<vector<type>>>(       \
             b, vector<vector<type>>(c, vector<type>(__VA_ARGS__))))

#define rep1(a) for (ll _ = 0; _ < (ll)(a); ++_)
#define rep2(i, a) for (ll i = 0; i < (ll)(a); ++i)
#define rep3(i, a, b) for (ll i = a; i < (ll)(b); ++i)
#define rep4(i, a, b, c) for (ll i = a; i < (ll)(b); i += (c))
#define rrep1(a) for (ll i = (a)-1; i >= (ll)(0); --i)
#define rrep2(i, a) for (ll i = (a)-1; i >= (ll)(0); --i)
#define rrep3(i, a, b) for (ll i = (b)-1; i >= (ll)(a); --i)
#define rrep4(i, a, b, c) for (ll i = (b)-1; i >= (ll)(a); i -= (c))
#define overload4(a, b, c, d, e, ...) e
#define rep(...) overload4(__VA_ARGS__, rep4, rep3, rep2, rep1)(__VA_ARGS__)
#define rrep(...) overload4(__VA_ARGS__, rrep4, rrep3, rrep2, rrep1)(__VA_ARGS__)

#define all(x) (x).begin(),(x).end()
#define len(x) (ll)(x.size())
#define elif else if
#define bit(x, i) (((x)>>(i))&1)

#define eb emplace_back
#define mp make_pair
#define mt make_tuple
#define fi first
#define se second

#define stoi stoll
#define abs llabs

#define MIN(v) *min_element(all(v))
#define MAX(v) *max_element(all(v))
#define LB(c, x) distance((c).begin(), lower_bound(all(c), (x)))
#define UB(c, x) distance((c).begin(), upper_bound(all(c), (x)))
#define UNIQUE(x) \
  sort(all(x)), x.erase(unique(all(x)), x.end()), x.shrink_to_fit()

ll popcnt(ll x) { return __builtin_popcountll(x); }
ll popcnt(u64 x) { return __builtin_popcountll(x); }
ll popcnt_mod_2(ll x) { return __builtin_parityll(x); }
ll popcnt_mod_2(u64 x) { return __builtin_parityll(x); }
ll topbit(ll x) { return (x == 0 ? -1 : 63 - __builtin_clzll(x)); }
ll topbit(u64 x) { return (x == 0 ? -1 : 63 - __builtin_clzll(x)); }
ll lowbit(ll x) { return (x == 0 ? -1 : __builtin_ctzll(x)); }
ll lowbit(u64 x) { return (x == 0 ? -1 : __builtin_ctzll(x)); }

template <typename T>
T floor(T a, T b) {
  return a / b - (a % b && (a ^ b) < 0);
}
template <typename T>
T ceil(T x, T y) {
  return floor(x + y - 1, y);
}
template <typename T>
T bmod(T x, T y) {
  return x - y * floor(x, y);
}
template <typename T>
pair<T, T> divmod(T x, T y) {
  T q = floor(x, y);
  return {q, x - q * y};
}

template<typename T> T SUM(const vector<T> &A) {
  T s = 0; for (auto &&a: A) s += a;
  return s;
}

template <typename T>
T POP(queue<T> &que) {
  T a = que.front();
  que.pop();
  return a;
}
template <typename T>
T POP(deque<T> &que) {
  T a = que.front();
  que.pop_front();
  return a;
}
template <typename T>
T POP(pq<T> &que) {
  T a = que.top();
  que.pop();
  return a;
}
template <typename T>
T POP(pqg<T> &que) {
  T a = que.top();
  que.pop();
  return a;
}
template <typename T>
T POP(vc<T> &que) {
  T a = que.back();
  que.pop_back();
  return a;
}

template <typename F>
ll binary_search(F check, ll ok, ll ng, bool check_ok = true) {
  if (check_ok) assert(check(ok));
  while (abs(ok - ng) > 1) {
    auto x = (ng + ok) / 2;
    (check(x) ? ok : ng) = x;
  }
  return ok;
}
template <typename F>
f128 binary_search_real(F check, f128 ok, f128 ng, ll iter = 100) {
  rep(iter) {
    f128 x = (ok + ng) / 2;
    (check(x) ? ok : ng) = x;
  }
  return (ok + ng) / 2;
}

// ? は -1
vc<int> s_to_vi(const string &S, char first_char) {
  vc<int> A(S.size());
  rep(i, S.size()) { A[i] = (S[i] != '?' ? S[i] - first_char : -1); }
  return A;
}

template <typename T, typename U>
vc<T> cumsum(vc<U> &A, ll off = 1) {
  ll N = A.size();
  vc<T> B(N + 1);
  rep(i, N) { B[i + 1] = B[i] + A[i]; }
  if (off == 0) B.erase(B.begin());
  return B;
}

// stable sort
template <typename T>
vi argsort(const vector<T> &A) {
  vi ids(len(A));
  iota(all(ids), 0);
  sort(all(ids),
       [&](ll i, ll j) { return (A[i] == A[j] ? i < j : A[i] < A[j]); });
  return ids;
}

// A[I[0]], A[I[1]], ...
template <typename T>
vc<T> rearrange(const vc<T> &A, const vi &I) {
  vc<T> B(len(I));
  rep(i, len(I)) B[i] = A[I[i]];
  return B;
}

template<typename T> inline bool chmax(T &a, T b) {return ((a<b)?(a=b,true):(false));}
template<typename T> inline bool chmin(T &a, T b) {return ((a>b)?(a=b,true):(false));}

inline void wt(const char c) { cout << c; }
inline void wt(const string s) { cout << s; }
inline void wt(const char *s) { cout << s; }

template <typename T>
void wt_integer(T x) {
  cout << (x);
}
template <typename T>
void wt_real(T x) {
  cout << fixed << setprecision(15) << (long double)(x);
}
template <typename T>
void wt_integer128(T x) {
  char buf[64];
  char *d = end(buf);
  d--; *d = '\0';
  __uint128_t tmp = ((x < 0)? -x : x);
  do {
    d--; *d = char(tmp%10 + '0'); tmp /= 10;
  } while (tmp);
  if (x < 0) {
    d--; *d = '-';
  }
  cout << d;
}

inline void wt(int x) { wt_integer(x); }
inline void wt(ll x) { wt_integer(x); }
inline void wt(i128 x) { wt_integer128(x); }
inline void wt(u32 x) { wt_integer(x); }
inline void wt(u64 x) { wt_integer(x); }
inline void wt(u128 x) { wt_integer128(x); }
inline void wt(double x) { wt_real(x); }
inline void wt(long double x) { wt_real(x); }
inline void wt(f128 x) { wt_real(x); }

template <class T, class U>
void wt(const pair<T, U> val) {
  wt(val.first); wt(' '); wt(val.second);
}
template <size_t N = 0, typename T>
void wt_tuple(const T t) {
  if constexpr (N < std::tuple_size<T>::value) {
    if constexpr (N > 0) { wt(' '); }
    const auto x = std::get<N>(t);
    wt(x);
    wt_tuple<N + 1>(t);
  }
}
template <class... T>
void wt(tuple<T...> tpl) {
  wt_tuple(tpl);
}
template <class T, size_t S>
void wt(const array<T, S> val) {
  auto n = val.size();
  for (size_t i = 0; i < n; i++) {
    if (i) wt(' ');
    wt(val[i]);
  }
}
template <class T>
void wt(const vector<T> val) {
  auto n = val.size();
  for (size_t i = 0; i < n; i++) {
    if (i) wt(' ');
    wt(val[i]);
  }
}

void print() { wt('\n'); }
template <class Head, class... Tail>
void print(Head &&head, Tail &&... tail) {
  wt(head);
  if (sizeof...(Tail)) wt(' ');
  print(forward<Tail>(tail)...);
}

void YES(bool t = 1) { print(t ? "YES" : "NO"); }
void NO(bool t = 1) { YES(!t); }
void Yes(bool t = 1) { print(t ? "Yes" : "No"); }
void No(bool t = 1) { Yes(!t); }
void yes(bool t = 1) { print(t ? "yes" : "no"); }
void no(bool t = 1) { yes(!t); }
void onez(bool t = 1) { print(t ? 1 : 0); }
#define endl '\n'
#define dump(x) {cerr << #x " = " << x << '\n';}
#line 2 "/opt/library/graph/base.hpp"

template <typename T>
struct Edge {
  ll frm, to;
  T cost;
  ll id;
};

template <typename T = ll, bool directed = false>
struct Graph {
  static constexpr bool is_directed = directed;
  ll N, M;
  using cost_type = T;
  using edge_type = Edge<T>;
  vector<edge_type> edges;
  vi indptr;
  vc<edge_type> csr_edges;
  vc<ll> vc_deg, vc_indeg, vc_outdeg;
  bool prepared;

  class OutgoingEdges {
  public:
    OutgoingEdges(const Graph* G, ll l, ll r) : G(G), l(l), r(r) {}

    const edge_type* begin() const {
      if (l == r) { return 0; }
      return &G->csr_edges[l];
    }

    const edge_type* end() const {
      if (l == r) { return 0; }
      return &G->csr_edges[r];
    }

  private:
    const Graph* G;
    ll l, r;
  };

  bool is_prepared() { return prepared; }

  Graph() : N(0), M(0), prepared(0) {}
  Graph(ll N) : N(N), M(0), prepared(0) {}

  void build(ll n) {
    N = n, M = 0;
    prepared = 0;
    edges.clear();
    indptr.clear();
    csr_edges.clear();
    vc_deg.clear();
    vc_indeg.clear();
    vc_outdeg.clear();
  }

  void add(ll frm, ll to, T cost = 1, ll i = -1) {
    assert(!prepared);
    assert(0 <= frm && 0 <= to && to < N);
    if (i == -1) i = M;
    auto e = edge_type({frm, to, cost, i});
    edges.eb(e);
    ++M;
  }

#ifdef FASTIO
  // wt, off
  void read_tree(bool wt = false, ll off = 1) { read_graph(N - 1, wt, off); }

  void read_graph(ll M, bool wt = false, ll off = 1) {
    for (ll m = 0; m < M; ++m) {
      LL(a, b);
      a -= off, b -= off;
      if (!wt) {
        add(a, b);
      } else {
        T c;
        read(c);
        add(a, b, c);
      }
    }
    build();
  }
#endif

  void build() {
    assert(!prepared);
    prepared = true;
    indptr.assign(N + 1, 0);
    for (auto&& e: edges) {
      indptr[e.frm + 1]++;
      if (!directed) indptr[e.to + 1]++;
    }
    for (ll v = 0; v < N; ++v) { indptr[v + 1] += indptr[v]; }
    auto counter = indptr;
    csr_edges.resize(indptr.back() + 1);
    for (auto&& e: edges) {
      csr_edges[counter[e.frm]++] = e;
      if (!directed)
        csr_edges[counter[e.to]++] = edge_type({e.to, e.frm, e.cost, e.id});
    }
  }

  OutgoingEdges operator[](ll v) const {
    assert(prepared);
    return {this, indptr[v], indptr[v + 1]};
  }

  vi deg_array() {
    if (vc_deg.empty()) calc_deg();
    return vc_deg;
  }

  pair<vi, vi> deg_array_inout() {
    if (vc_indeg.empty()) calc_deg_inout();
    return {vc_indeg, vc_outdeg};
  }

  ll deg(ll v) {
    if (vc_deg.empty()) calc_deg();
    return vc_deg[v];
  }

  ll in_deg(ll v) {
    if (vc_indeg.empty()) calc_deg_inout();
    return vc_indeg[v];
  }

  ll out_deg(ll v) {
    if (vc_outdeg.empty()) calc_deg_inout();
    return vc_outdeg[v];
  }

#ifdef FASTIO
  void debug() {
    print("Graph");
    if (!prepared) {
      print("frm to cost id");
      for (auto&& e: edges) print(e.frm, e.to, e.cost, e.id);
    } else {
      print("indptr", indptr);
      print("frm to cost id");
      rep(v, N) for (auto&& e: (*this)[v]) print(e.frm, e.to, e.cost, e.id);
    }
  }
#endif

  vi new_idx;
  vc<bool> used_e;

  // G における頂点 V[i] が、新しいグラフで i になるようにする
  // {G, es}
  Graph<T, directed> rearrange(vi V, bool keep_eid = 0) {
    if (len(new_idx) != N) new_idx.assign(N, -1);
    if (len(used_e) != M) used_e.assign(M, 0);
    ll n = len(V);
    rep(i, n) new_idx[V[i]] = i;
    Graph<T, directed> G(n);
    vi history;
    rep(i, n) {
      for (auto&& e: (*this)[V[i]]) {
        if (used_e[e.id]) continue;
        ll a = e.frm, b = e.to;
        if (new_idx[a] != -1 && new_idx[b] != -1) {
          history.eb(e.id);
          used_e[e.id] = 1;
          ll eid = (keep_eid ? e.id : -1);
          G.add(new_idx[a], new_idx[b], e.cost, eid);
        }
      }
    }
    rep(i, n) new_idx[V[i]] = -1;
    for (auto&& eid: history) used_e[eid] = 0;
    G.build();
    return G;
  }

private:
  void calc_deg() {
    assert(vc_deg.empty());
    vc_deg.resize(N);
    for (auto&& e: edges) vc_deg[e.frm]++, vc_deg[e.to]++;
  }

  void calc_deg_inout() {
    assert(vc_indeg.empty());
    vc_indeg.resize(N);
    vc_outdeg.resize(N);
    for (auto&& e: edges) { vc_indeg[e.to]++, vc_outdeg[e.frm]++; }
  }
};
#line 3 "main.cpp"

int solve();
int main() {
  cin.tie(nullptr);
  ios_base::sync_with_stdio(false);
  while (!solve()) {break;}
  return 0;
}

int solve() {
  ll N, Q, u, v, a, b;
  cin >> N;
  Graph<ll> G(N);
  rep(N) {
    cin >> u >> v;
    u--; v--;
    G.add(u, v);
  }
  G.build();

  stack<ll> hst;
  ll pos = -1;
  vc<bool> seen(N, false), finished(N, false);
  auto dfs = [&](auto self, ll v, ll p) -> void {
    seen[v] = true;
    hst.push(v);
    for (auto e: G[v]) {
      if (e.to == p) continue;
      if (finished[e.to]) continue;
      if (seen[e.to] and !finished[e.to]) {
        pos = e.to;
        return;
      }
      self(self, e.to, v);
      if (pos != -1) return;
    }
    hst.pop();
    finished[v] = true;
  };
  dfs(dfs, 0, -1);

  set<ll> cycle;
  while (!hst.empty()) {
    ll t = hst.top(); hst.pop();
    cycle.emplace(t);
    if (pos == t) break;
  }

  cin >> Q;
  rep(Q) {
    cin >> a >> b;
    a--; b--;
    if (cycle.count(a) and cycle.count(b)) print(2);
    else print(1);
  }
  return 0;
}
accuracy: 1
time_ms: 60
memory_kb: 29752
final_rank: 11