#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;
typedef long long ll;
typedef pair<int, int> pi;
int n, m, q;
struct query {
int op, u, v, ans;
}qry[N];
int h[N], etot = 1;
struct edge {
int from, to, nxt, ans;
}e[N];
void add (int u, int v) {
e[++ etot] = {u, v, h[u]}, h[u] = etot;
}
void clean_edge () {
etot = 0;
memset(h, 0, sizeof h);
}
int dfth[N], low[N], tmp;
int st[N], stack_top;
int idx, bel[N];
void tarjan (int u, int from) {
dfth[u] = low[u] = ++ tmp;
st[++ stack_top] = u;
for (int i = h[u]; i; i = e[i].nxt) {
if (i == (from ^ 1)) continue;
int v = e[i].to;
if (!dfth[v]) {
tarjan(v, i), low[u] = min(low[u], low[v]);
}
else low[u] = min(low[u], dfth[v]);
}
if (low[u] == dfth[u]) {
bel[u] = ++ idx;
while (st[stack_top] != u) bel[st[stack_top]] = idx, stack_top --;
stack_top --;
}
}
void rebuild () {
int bef = etot;
clean_edge();
for (int i = 2; i <= bef; i ++) {
int u = e[i].from, v = e[i].to;
if (bel[u] != bel[v]) {
add (bel[u], bel[v]);
}
}
}
int dfn[N], to[N], fath[N], siz[N], son[N], top[N], dep[N];
int cur;
void dfs1 (int u, int fa) {
fath[u] = fa, siz[u] = 1, dep[u] = dep[fa] + 1;
for (int i = h[u]; i; i = e[i].nxt) {
int v = e[i].to;
if (v == fa) continue;
dfs1 (v, u);
siz[u] += siz[v];
if (siz[v] > siz[son[u]]) son[u] = v;
}
}
void dfs2 (int u, int tp) {
dfn[++ cur] = u, to[cur] = u, top[u] = tp;
if (son[u]) dfs2 (son[u], tp);
for (int i = h[u]; i ; i = e[i].nxt) {
int v = e[i].to;
if (v == fath[u] || v == son[u]) continue;
dfs2 (v, v);
}
}
namespace t {
int sum[N << 2], tag[N << 2];
#define mid (l + r >> 1)
#define ls p << 1, l, mid
#define rs p << 1 | 1, mid + 1, r
void pushup (int p, int l, int r) {
sum[p] = sum[p << 1] + sum[p << 1 | 1];
}
void change (int p, int l, int r, int v) {
tag[p] = v, sum[p] = v * (r - l + 1);
}
void pushdown (int p, int l, int r) {
if(tag[p] != -1) change (ls, tag[p]), change(rs, tag[p]), tag[p] = -1;
}
void build (int p, int l, int r) {
tag[p] = -1;
if (l == r) sum[p] = 1;
else build (ls), build (rs), tag[p] = 1, pushup(p, l, r);
}
void updata (int p, int l, int r, int ql, int qr) {
if (ql <= l && r <= qr) {change(p, l, r, 0); return;}
pushdown(p, l, r);
if (mid >= ql) updata (ls, ql, qr);
if (mid < qr) updata (rs, ql, qr);
pushup(p, l, r);
}
int getsum (int p, int l, int r, int ql, int qr) {
if (ql <= l && r <= qr) return sum[p];
if (l > qr || r < ql) return 0;
pushdown(p, l, r);
return getsum(ls, ql, qr) + getsum(rs, ql, qr);
}
};
void updata (int u, int v) {
while (top[u] != top[v]) {
if (dep[top[u]] < dep[top[v]]) swap(u, v);
t::updata (1, 1, n, dfn[top[u]], dfn[u]);
u = fath[top[u]];
}
if (u == v) return;
if (dep[u] < dep[v]) swap(u, v);
t::updata (1, 1, n, dfn[v] + 1, dfn[u]);
}
int getsum (int u, int v) {
int res = 0;
while (top[u] != top[v]) {
if (dep[top[u]] < dep[top[v]]) swap(u, v);
res += t::getsum (1, 1, n, dfn[top[u]], dfn[u]);
u = fath[top[u]];
}
if (u == v) return res;
if (dep[u] < dep[v]) swap(u, v);
res += t::getsum (1, 1, n, dfn[v] + 1, dfn[u]);
return res;
}
pi eg[N];
map<pi, bool> mark;
signed main() {
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin >> n >> m;
for (int i = 1; i <= m; i ++) {
cin >> eg[i].first >> eg[i].second;
if (eg[i].first > eg[i].second) swap(eg[i].first, eg[i].second);
}
int op, u, v;
while (cin >> op) {
if (op == -1) break;
cin >> u >> v;
qry[++ q] = {op, u, v};
if (u > v) swap(u, v);
if (op == 0) mark[{u, v}] = 1;
}
for (int i = 1; i <= m; i ++) {
if (!mark[eg[i]]) {
add (eg[i].first, eg[i].second);
add (eg[i].second, eg[i].first);
}
}
tarjan(1, 0);
rebuild();
dfs1 (1, 0);
dfs2 (1, 1);
t::build(1, 1, idx);
for (int i = q; i >= 1; i --) {
int op = qry[i].op, u = qry[i].u, v = qry[i].v;
if (op == 0) updata (bel[u], bel[v]);
else qry[i].ans = getsum(bel[u], bel[v]);
}
for (int i = 1; i <= q; i ++) {
if (qry[i].op == 1) cout << qry[i].ans << endl;
}
return 0;
}