Rt
#include<bits/stdc++.h>
#define ll long long
#define int ll
#define debug(x) cout<<#x<<":"<<x,puts("");
#define FOR(i,a,b) for(ll i=(a); i<=(b); ++i)
#define ROF(i,a,b) for(ll i=(a); i>=(b); --i)
//
//
//
using namespace std;
inline ll read() {
ll f = 0, t = 0;
char c = getchar();
while (!isdigit(c)) t |= (c == '-'), c = getchar();
while (isdigit(c)) f = (f << 3) + (f << 1) + c - 48, c = getchar();
return t ? -f : f;
}
const int MX = 1e6 + 10, MM = 1e6 + 10;
int x[MX], y[MX];
map<int, map<int, int> >v;
vector<int>edge[MM];
int V[MX];
struct {
int op;
int x, y;
} H[MX];
int F[MM];
int n, m, CNT;
int Find(int x) {
if (F[x] == x) return x;
return F[x] = Find(F[x]);
}
int V2[MX];
void make_tree() {
FOR(i, 1, n) F[i] = i;
FOR(i, 1, m) {
if (V[i]) continue;
int X = Find(x[i]), Y = Find(y[i]);
if (X == Y) continue;
V2[i] = 1;
edge[x[i]].push_back(y[i]);
edge[y[i]].push_back(x[i]);
F[X] = Y;
}
}
int fa[MM], son[MM], siz[MM], dep[MM];
void dfs(int x, int f) {
fa[x] = f, dep[x] = dep[fa[x]] + 1;
siz[x] = 1;
for (int v : edge[x]) {
if (v == fa[x]) continue;
dfs(v, x);
siz[x] += siz[v];
if (siz[v] > siz[son[x]]) son[x] = v;
}
}
int top[MM], idx[MM], Tim;
int idu[MX], Tim2, idd[MX];
void dfs2(int x, int Top) {
idx[x] = ++Tim, top[x] = Top;
if (son[x] == 0) return;
idu[son[x]] = ++Tim2;
idd[x] = Tim2;
dfs2(son[x], Top);
for (int y : edge[x]) {
if (y == fa[x] || y == son[x]) continue;
idu[y] = ++Tim2;
dfs2(y, y);
}
}
struct sky {
int mi, sum;
} tree[MX * 4];
int lzy[MX * 4];
#define lw(x) (x<<1)
#define rw(x) (x<<1|1)
#define mid ((l+r)/2)
void push_down(int x) {
lzy[lw(x)] += lzy[x];
lzy[rw(x)] += lzy[x];
tree[lw(x)].mi += lzy[x];
tree[rw(x)].mi += lzy[x];
lzy[x] = 0;
return;
}
void push_up(int x) {
if (tree[lw(x)].mi == tree[rw(x)].mi) tree[x].sum = tree[lw(x)].sum + tree[rw(x)].sum, tree[x].mi = tree[lw(x)].mi;
else if (tree[lw(x)].mi < tree[rw(x)].mi) tree[x] = tree[lw(x)];
else tree[x] = tree[rw(x)];
}
void build(int x, int l, int r) {
if (l == r) {
tree[x].sum = 1;
tree[x].mi = 1;
return;
}
build(lw(x), l, mid);
build(rw(x), mid + 1, r);
push_up(x);
}
void change(int x, int l, int r, int ln, int rn, int w) {
if (ln > rn) return;
if (ln <= l && r <= rn) {
tree[x].mi += w;
lzy[x] += w;
return;
}
if (lzy[x]) push_down(x);
if (ln <= mid) change(lw(x), l, mid, ln, rn, w);
if (mid < rn) change(rw(x), mid + 1, r, ln, rn, w);
push_up(x);
}
int find_T(int x, int l, int r, int ln, int rn) {
if (ln > rn) return 0;
if (lzy[x]) push_down(x);
if (ln <= l && r <= rn) {
if (tree[x].mi == 1) return tree[x].sum;
return 0;
}
if (lzy[x]) push_down(x);
int tmp = 0;
if (ln <= mid) tmp = find_T(lw(x), l, mid, ln, rn);
if (mid < rn) tmp += find_T(rw(x), mid + 1, r, ln, rn);
push_up(x);
return tmp;
}
int find(int x, int y) {
int cnt = 0;
while (top[x] != top[y]) {
if (dep[top[x]] < dep[top[y]]) swap(x, y);
cnt += find_T(1, 1, n - 1, max(1ll, idu[top[x]]), idu[x]);
x = fa[top[x]];
}
if (dep[x] < dep[y]) swap(x, y);
cnt += find_T(1, 1, n - 1, idd[y], idu[x]);
return cnt;
}
void Change(int x, int y, int w) {
while (top[x] != top[y]) {
if (dep[top[x]] < dep[top[y]]) swap(x, y);
change(1, 1, n - 1, max(1ll, idu[top[x]]), idu[x], w);
x = fa[top[x]];
}
if (dep[x] < dep[y]) swap(x, y);
change(1, 1, n - 1, idd[y], idu[x], w);
}
signed main() {
ios::sync_with_stdio(0), cout.tie(0);
n = read(), m = read();
FOR(i, 1, m) {
x[i] = read(), y[i] = read();
v[x[i]][y[i]] = i;
}
int op = read();
while (op != -1) {
int x = read(), y = read();
H[++CNT] = {op, x, y};
if (op == 0) V[v[x][y]] = 1;
op = read();
}
make_tree();
dfs(1, 0);
dfs2(1, 1);
build(1, 1, n - 1);
FOR(i, 1, m) if (!V2[i]) Change(x[i], y[i], 1);
FOR(i, 1, CNT) {
if (H[i].op == 0) Change(H[i].x, H[i].y, -1);
else cout << find(H[i].x, H[i].y) << "\n";
}
return 0;
}