Code:

#include <map>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
using namespace std;

void setIO(string a){
    freopen((a+".in").c_str(),"r",stdin);
    freopen((a+".out").c_str(),"w",stdout);
}

#define N 30005
#define Q 40005
#define M 100005

int n,m,cnt=1;
int head[N];
int to[M<<1];
int nex[M<<1];

int siz[N];
int f[N];
int son[N];
int dep[N];
int uu[M<<1];
int vv[M<<1];
bool tag[M<<1];
bool vis[N];

void addedge(int u,int v){
    nex[++cnt]=head[u],head[u]=cnt,to[cnt]=v;
    uu[cnt]=u,vv[cnt]=v;
}

void dfs1(int u,int fa,int depth){
    siz[u]=1,f[u]=fa,vis[u]=1,dep[u]=depth+1;
    for(int v=head[u];v;v=nex[v]){
        if(!vis[to[v]]&&to[v]!=fa) {
            tag[v]=tag[v^1]=1;
            dfs1(to[v],u,depth+1);
            siz[u]+=siz[to[v]];
            if(siz[to[v]]>siz[son[u]]) son[u]=to[v];
        }
    }
}

int A[N];
int top[N];
int cnt2=0;

void dfs2(int u,int tp){
    top[u]=tp;
    A[u]=++cnt2;
    if(son[u])dfs2(son[u],tp);
    for(int v=head[u];v;v=nex[v])
        if(to[v]!=son[u]&&to[v]!=f[u]&&tag[v])dfs2(to[v],to[v]);
    //if(!son[u]) son[u]=u;
}

int sumv[N<<2];
int lazy[N<<2];

#define lson (o<<1)
#define rson (o<<1)|1

void pushup(int o){
    sumv[o]=sumv[lson]+sumv[rson];
    if(lazy[lson]&&lazy[rson]) lazy[o]=1,sumv[o]=0;
}
void build(int l,int r,int o){
    if(l>r)return;
    if(l==r) {
        sumv[o]=1;
        if(l==1)sumv[o]=0;
        return;
    }
    int mid=(l+r)>>1;
    build(l,mid,lson);
    build(mid+1,r,rson);
    pushup(o);
}
void modify(int l,int r,int o,int L,int R){
    if(l>r||r<L||l>R)return;
    if(lazy[o])return;
    if(l>=L&&r<=R){
        sumv[o]=0;
        lazy[o]=1;
        return;
    }
    int mid=(l+r)>>1;
    modify(l,mid,lson,L,R);
    modify(mid+1,r,rson,L,R);
    pushup(o);
}
int query(int l,int r,int o,int L,int R){

    if(lazy[o]||l>r||r<L||l>R)return 0;
    if(l>=L&&r<=R)return sumv[o];
    int mid=(l+r)>>1;
    return query(l,mid,lson,L,R)+query(mid+1,r,rson,L,R);
}
void update(int a,int b){
    while(top[a]!=top[b]){
        if(dep[top[a]]>dep[top[b]]) swap(a,b);
        modify(1,n,1,A[top[b]],A[b]),b=f[top[b]];
    }
    if(a==b)return ;
    if(dep[a]>dep[b]) swap(a,b); 
    modify(1,n,1,A[son[a]],A[b]);
}

int lookup(int a,int b){
    int sums=0;
    while(top[a]!=top[b]){
        if(dep[top[a]]>dep[top[b]]) swap(a,b);
        sums+=query(1,n,1,A[top[b]],A[b]);
        b=f[top[b]];
    }
    if(a==b) return sums;
    if(dep[a]>dep[b])swap(a,b);
    sums+=query(1,n,1,A[son[a]],A[b]);
    return sums;
}

struct Edge{
    int from,to,t;
    Edge(int from=0,int to=0,int t=0):from(from),to(to),t(t){}
}edges[M];
struct Ask{
    int a,b,c;
    Ask(int a=0,int b=0,int c=0):a(a),b(b),c(c){}
}asks[Q];
typedef pair<int,int> P;
map<P,int>idx;
int curr;
int answer[Q];
int cnans;
int main(){
    //setIO("input");
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;++i){
        int a,b;
        scanf("%d%d",&a,&b);
        if(a>b)swap(a,b);
        edges[i]=Edge(a,b,0);
        idx[P(a,b)]=i;
    }
    while(1){
        int a,b,c;
        scanf("%d%d%d",&c,&b,&a);
        if(c==-1) break;
        if(a>b)swap(a,b);
        asks[++curr]=Ask(a,b,c);
        if(c!=1&&idx[P(a,b)]) edges[idx[P(a,b)]].t=1;
    }
    for(int i=1;i<=m;++i)
        if(edges[i].t!=1) 
            addedge(edges[i].from,edges[i].to),addedge(edges[i].to,edges[i].from);
    dfs1(1,0,0);
    dfs2(1,1);
    build(1,n,1);
    for(int i=2;i<=cnt;i+=2)
        if(!tag[i]){
            tag[i]=tag[i^1]=1;
            update(uu[i],vv[i]);
        }
        
    for(int i=curr;i>=1;--i)
    {
        if(asks[i].c==1) answer[++cnans]=lookup(asks[i].a,asks[i].b);
        else update(asks[i].a,asks[i].b);
    }
    for(int i=cnans;i>=1;--i) printf("%d\n",answer[i]);
    return 0;
}