做法:边双缩点+树剖
#include <bits/stdc++.h>
using namespace std;
#define pii pair<int,int>
#define fi first
#define se second
const int M=1e5+5;
const int N=3e4+5;
int n,m,cnt=1,df,bcc,tot;
int head[N],dep[N],dfn[N],low[N],ct[M<<1],vis[N],bel[N],siz[N],son[N],f[N],top[N],ans[N];
struct edge{
int x,y,op;
}b[M];
struct node{
int to,ne;
}e[M];
void add(int x,int y){
e[++cnt]=(node){y,head[x]};
head[x]=cnt;
}
void tarjan(int x,int ed){
dfn[x]=low[x]=++df;
ed^=1;
for(int i=head[x];i;i=e[i].ne){
int y=e[i].to;
if(!dfn[y]){
tarjan(y,i);
low[x]=min(low[x],low[y]);
if(low[y]>dfn[x]){
ct[i]=ct[i^1]=1;
}
}else if(i!=ed) low[x]=min(low[x],dfn[y]);
}
}
void dfs(int x){
vis[x]=1;
bel[x]=bcc;
for(int i=head[x];i;i=e[i].ne){
if(!ct[i]){
int y=e[i].to;
if(!vis[y]){
dfs(y);
}
}
}
}
struct mm{
int x,y;
}c[M];
map<pii,int> mp;
vector<int> g[N];
void add2(int x,int y){
g[x].push_back(y);
}
void dfs2(int x,int fa){
siz[x]=1;
dep[x]=dep[fa]+1;
f[x]=fa;
for(int y:g[x]){
if(y!=fa){
dfs2(y,x);
siz[x]+=siz[y];
if(siz[y]>siz[son[x]]){
son[x]=y;
}
}
}
}
void dfs3(int x,int tp){
top[x]=tp;
dfn[x]=++df;
if(son[x]) dfs3(son[x],tp);
for(int y:g[x]){
if(y!=f[x]&&y!=son[x]){
// cout<<x<<" "<<y<<"\n";
dfs3(y,y);
}
}
}
struct tr{
int t[N<<2],tg[N<<2];
tr(){memset(tg,-1,sizeof(tg));}
void pp(int p){
t[p]=t[p<<1]+t[p<<1|1];
}
void build(int p,int l,int r){
if(l==r){
t[p]=1;
return ;
}
int mid=l+r>>1;
build(p<<1,l,mid);
build(p<<1|1,mid+1,r);
pp(p);
}
void add(int p,int l,int r){
t[p]=0;
tg[p]=0;
}
void pd(int p,int l,int r){
if(tg[p]!=-1){
int mid=l+r>>1;
add(p<<1,l,mid);
add(p<<1|1,mid+1,r);
tg[p]=-1;
}
}
void modify(int p,int l,int r,int ql,int qr){
if(l>=ql&&r<=qr){
add(p,l,r);
return ;
}
int mid=l+r>>1;
pd(p,l,r);
if(ql<=mid) modify(p<<1,l,mid,ql,qr);
if(qr>mid) modify(p<<1|1,mid+1,r,ql,qr);
pp(p);
}
int query(int p,int l,int r,int ql,int qr){
if(l>=ql&&r<=qr){
return t[p];
}
int mid=l+r>>1;
int sm=0;
pd(p,l,r);
if(ql<=mid) sm+=query(p<<1,l,mid,ql,qr);
if(qr>mid) sm+=query(p<<1|1,mid+1,r,ql,qr);
return sm;
}
}sg;
void mroad(int x,int y){
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]){
swap(x,y);
}
sg.modify(1,1,bcc,dfn[top[x]],dfn[x]);
x=f[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
if(x==y){
return ;
}
sg.modify(1,1,bcc,dfn[x]+1,dfn[y]);
}
void qroad(int x,int y,int id){
int sm=0;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]){
swap(x,y);
}
sm+=sg.query(1,1,bcc,dfn[top[x]],dfn[x]);
x=f[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
if(x==y){
ans[id]=sm;
return ;
}
sm+=sg.query(1,1,bcc,dfn[x]+1,dfn[y]);
ans[id]=sm;
}
int main(){
ios::sync_with_stdio(0),cin.tie(0);
cin>>n>>m;
for(int i=1,x,y;i<=m;i++){
cin>>x>>y;
c[i]=(mm){x,y};
}
while(1){
int op,x,y;
cin>>op;
if(op==-1) break;
cin>>x>>y;
b[++tot]=(edge){x,y,op};
if(op==0){
mp[{x,y}]=mp[{y,x}]=1;
}
}
for(int i=1;i<=m;i++){
int x=c[i].x,y=c[i].y;
if(!mp[{x,y}]){
add(x,y);
add(y,x);
}
}
tarjan(1,0);
for(int i=1;i<=n;i++){
if(!vis[i]){
bcc++;
dfs(i);
}
}
for(int x=1;x<=n;x++){
for(int i=head[x];i;i=e[i].ne){
int y=e[i].to;
if(bel[x]!=bel[y]){
add2(bel[x],bel[y]);
}
}
}
df=0;
dfs2(bel[1],0);
dfs3(bel[1],bel[1]);
sg.build(1,1,bcc);
for(int i=tot;i>=1;i--){
int x=b[i].x,y=b[i].y,op=b[i].op;
if(op==1){
qroad(bel[x],bel[y],i);
}
else{
mroad(bel[x],bel[y]);
}
}
for(int i=1;i<=tot;i++){
if(b[i].op==1)
cout<<ans[i]<<"\n";
}
return 0;
}