不会lct,所以只能树剖乱搞
一般这种删边的题都是离线倒着做,变成加边
他要求的结果其实就是缩点以后两点间的距离。
然后先根据最后剩下的边随便做出一个生成树,然后假装把剩下的边当成加边操作以后处理
这样的话,就可以做树剖来维护现在的两点间距离。
然后考虑加边,其实就是加了一条边然后某一处成环了,缩成了一个点。
这样的话,就可以把这条边两个端点间的距离都改成0,假装缩了点。
最后再倒着输出答案就行了。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
#include<cmath>
#define inf 0x3f3f3f3f
#define LL long long int
using namespace std;
const int maxn=,maxm=,maxq=; inline LL rd(){
LL x=;char c=getchar();int neg=;
while(c<''||c>''){if(c=='-') neg=-;c=getchar();}
while(c>=''&&c<='') x=x*+c-'',c=getchar();
return x*neg;
} struct Edge{
int a,b,ne;bool used,flag;
}eg[maxm*];
int N,M;
int egh[maxn],ect;
int que[maxq][],ans[maxq],qct;
int fa[maxn],dep[maxn],wson[maxn],siz[maxn],top[maxn],root[maxn],len[maxn];
int ch[maxn*][],val[maxn*],pct;
bool laz[maxn*];
map<int,int> mp; inline void adeg(int a,int b){
eg[ect].a=a;eg[ect].b=b;eg[ect].ne=egh[a];eg[ect].used=;egh[a]=ect++;
} inline void pushdown(int p){
if(!laz[p]) return;
val[ch[p][]]=val[ch[p][]]=laz[p]=;
laz[ch[p][]]=laz[ch[p][]]=;
}
inline void update(int p){pushdown(p);val[p]=val[ch[p][]]+val[ch[p][]];} void build(int &p,int l,int r){
p=++pct;
if(l==r) val[p]=;
else{
int m=l+r>>;
build(ch[p][],l,m);build(ch[p][],m+,r);
update(p);
}
} int query(int p,int l,int r,int x,int y){
if(x<=l&&r<=y) return val[p];
else{
pushdown(p);int m=l+r>>,re=;
if(x<=m) re+=query(ch[p][],l,m,x,y);
if(y>=m+) re+=query(ch[p][],m+,r,x,y);
return re;
}
} void change(int p,int l,int r,int x,int y){
if(x<=l&&r<=y){
val[p]=;laz[p]=;pushdown(p);
}else if(val[p]!=){
pushdown(p);int m=l+r>>;
if(x<=m) change(ch[p][],l,m,x,y);
if(y>=m+) change(ch[p][],m+,r,x,y);
update(p);
}
} void dfs1(int x){
siz[x]=;int ma=;
for(int i=egh[x];i!=-;i=eg[i].ne){
int b=eg[i].b;
if(!eg[i].used||dep[b]) continue;
eg[i].flag=eg[i^].flag=;
fa[b]=x;dep[b]=dep[x]+;
dfs1(b);siz[x]+=siz[b];
if(siz[b]>ma) ma=siz[b],wson[x]=b;
}
} void dfs2(int x){
if(x!=wson[fa[x]]){int d=;
for(int i=x;i;i=wson[i]) top[i]=x,d++;
build(root[x],,d);len[x]=d;
}for(int i=egh[x];i!=-;i=eg[i].ne){
int b=eg[i].b;
if(eg[i].flag&&fa[x]!=b) dfs2(b);
}
} void solveC(int x,int y){
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]) swap(x,y);
change(root[top[x]],,len[top[x]],,dep[x]-dep[top[x]]+);x=fa[top[x]];
}if(x==y) return;
if(dep[x]>dep[y]) swap(x,y);
change(root[top[x]],,len[top[x]],dep[x]-dep[top[x]]+,dep[y]-dep[top[y]]+);
}
int solveQ(int x,int y){
int re=;
while(top[x]!=top[y]){ if(dep[top[x]]<dep[top[y]]) swap(x,y);
re+=query(root[top[x]],,len[top[x]],,dep[x]-dep[top[x]]+);x=fa[top[x]];
}if(x==y) return re;
if(dep[x]>dep[y]) swap(x,y);
return re+query(root[top[x]],,len[top[x]],dep[x]-dep[top[x]]+,dep[y]-dep[top[y]]+);
} int main(){
int i,j,k;
N=rd();M=rd();memset(egh,-,sizeof(egh));
for(i=;i<=M;i++){
int a=rd(),b=rd();
mp[a*N+b]=ect;adeg(a,b);
mp[b*N+a]=ect;adeg(b,a);
}while(++qct){
int a=rd();if(a==-) break;
int b=rd(),c=rd();
que[qct][]=a;que[qct][]=b;que[qct][]=c;
if(!a){
int x=mp[b*N+c];
eg[x].used=eg[x^].used=;
}
}dep[]=;dfs1();dfs2();
for(i=;i<ect;i++){
if((!eg[i].flag)&&eg[i].used) solveC(eg[i].a,eg[i].b);
}int act=;
for(i=qct-;i;i--){
if(!que[i][]) solveC(que[i][],que[i][]);
else ans[++act]=solveQ(que[i][],que[i][]);
}for(i=act;i;i--) printf("%d\n",ans[i]);
return ;
}