#include <iostream>
#include <cassert>
#include <queue>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <bitset>
#include <random>
#include <ctime>
#include <queue>
#include <map>
#include <set>
using namespace std;
#define int long long
#define pii pair<int, int>
#define eb emplace_back
#define F first
#define S second
#define test(x) cout << "Test: " << (x) << '\n'
#define lowbit(x) (x & -x)
#define debug puts("qwq");
#define open(x) freopen(#x".in", "r", stdin);freopen(#x".out", "w", stdout);
#define close fclose(stdin);fclose(stdout);
namespace FastIO {
template <typename T = int>
inline T read() {
T s = 0, w = 1;
char c = getchar();
while (!isdigit(c)) {
if (c == '-') w = -1;
c = getchar();
}
while (isdigit(c)) s = (s << 1) + (s << 3) + (c ^ 48), c = getchar();
return s * w;
}
template <typename T>
inline void read(T &s) {
s = 0;
int w = 1;
char c = getchar();
while (!isdigit(c)) {
if (c == '-') w = -1;
c = getchar();
}
while (isdigit(c)) s = (s << 1) + (s << 3) + (c ^ 48), c = getchar();
s = s * w;
}
template <typename T, typename... Arp> inline void read(T &x, Arp &...arp) {
read(x), read(arp...);
}
template <typename T>
inline void write(T x, char ch = '\n') {
if (x < 0) x = -x, putchar('-');
static char stk[25];
int top = 0;
do {
stk[top++] = x % 10 + '0', x /= 10;
} while (x);
while (top) putchar(stk[--top]);
putchar(ch);
return;
}
template <typename T>
inline void smax(T &x, T y) {
if (x < y) x = y;
}
template <typename T>
inline void smin(T &x, T y) {
if (x > y) x = y;
}
void quit() {
exit(0);
}
} using namespace FastIO;
const int N = 1e5 + 19;
vector<int> g[N];
int dep[N], fa[N], son[N], siz[N], cnt, dfn[N], top[N], rnk[N], n, m, q, no[N], len;
pair<int, int> a[N], b[N];
pair<int, pii> Q[N];
struct DSU {
int f[N];
void init(int n) { for (int i = 1; i <= n; ++i) f[i] = i; }
int find(int x) { return f[x] == x ? x : f[x] = find(f[x]); }
void merge(int x, int y) { f[find(x)] = find(y); }
} dsu;
void dfs1(int u, int f) {
fa[u] = f; dep[u] = dep[f] + 1; siz[u] = 1;
for (auto i : g[u]) {
if (i == f) continue;
dfs1(i, u);
if (siz[i] > siz[son[u]]) son[u] = i;
siz[u] += siz[i];
}
}
void dfs2(int u, int f) {
top[u] = f; dfn[u] = ++cnt; rnk[cnt] = u;
if (son[u]) dfs2(son[u], f);
for (auto i : g[u]) if (i != fa[u] && i != son[u]) dfs2(i, i);
}
struct SegTree {
int cnt[N << 2];
#define ls (k << 1)
#define rs (k << 1 | 1)
#define mid ((l + r) >> 1)
void build(int k, int l, int r) {
cnt[k] = r - l + 1;
if (l == r) return ;
build(ls, l, mid); build(rs, mid+1, r);
}
void modify(int k, int l, int r, int L, int R) {
if (L <= l && r <= R) return cnt[k] = 0, void();
if (L <= mid) modify(ls, l, mid, L, R);
if (R > mid) modify(rs, mid+1, r, L, R);
cnt[k] = cnt[ls] + cnt[rs];
}
int query(int k, int l, int r, int L, int R) {
if (L <= l && r <= R) return cnt[k];
int ans = 0;
if (L <= mid) ans += query(ls, l, mid, L, R);
if (R > mid) ans += query(rs, mid+1, r, L, R);
return ans;
}
} seg;
void solve(int u, int v) {
while (top[u] != top[v]) {
if (dep[top[u]] > dep[top[v]]) swap(u, v);
seg.modify(1, 1, n, dfn[top[v]], dfn[v]);
v = fa[top[v]];
}
if (dep[u] > dep[v]) swap(u, v);
if (u ^ v) seg.modify(1, 1, n, dfn[u]+1, dfn[v]);
} int query(int u, int v) {
int ans = 0;
while (top[u] != top[v]) {
if (dep[top[u]] > dep[top[v]]) swap(u, v);
ans += seg.query(1, 1, n, dfn[top[v]], dfn[v]);
v = fa[top[v]];
}
if (dep[u] > dep[v]) swap(u, v);
if (u ^ v) ans += seg.query(1, 1, n, dfn[u]+1, dfn[v]);
return ans;
}
signed main() {
read(n, m); dsu.init(n);
for (int i = 1; i <= m; ++i) {
read(a[i].F, a[i].S);
}
sort(a + 1, a + 1 + m);
for (int op, u, v; (op = read()) != -1; ) {
read(u, v); Q[++q] = {op, {u, v}};
auto x = lower_bound(a + 1, a + 1 + m, make_pair(u, v));
if (!op && *x == make_pair(u, v)) no[x - a] = 1;
}
for (int i = 1; i <= m; ++i) {
if (!no[i]) {
if (dsu.find(a[i].F) == dsu.find(a[i].S)) b[++len] = a[i];
else g[a[i].F].eb(a[i].S), g[a[i].S].eb(a[i].F), dsu.merge(a[i].F, a[i].S);
}
} dfs1(1, 0); dfs2(1, 1); seg.build(1, 1, n); seg.modify(1, 1, n, 1, 1);
for (int i = 1; i <= len; ++i) {
solve(b[i].F, b[i].S);
} vector<int> ans;
for (int i = q; i; --i) {
if (Q[i].F == 1) ans.eb(query(Q[i].S.F, Q[i].S.S));
else solve(Q[i].S.F, Q[i].S.S);
} reverse(ans.begin(), ans.end());
for (int i : ans) write(i);
return 0;
}