题解:
x→y
x
→
y
的所有路径都可以由
x→y
x
→
y
在
dfs
d
f
s
树上的路径抑或图中的环得到。
然后问题变为了动态维护 dfs d f s 树和所有环(支持删边加边),这个显然是不大可做的,不过如果只有加边操作就很简单了。
然后发现可以离线,就可以把一条边的出现区间放到 logn log n 个线段树的节点上,然后从上往下 dfs d f s 线段树处理所有询问即可。
注意要支持撤销,所以加边用按秩合并的并查集。
#include <bits/stdc++.h>
using namespace std;
typedef pair<int,int> pii;
inline int rd() {
char ch=getchar(); int i=0,f=1;
while(!isdigit(ch)) {if(ch=='-')f=-1; ch=getchar();}
while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=getchar();}
return i*f;
}
const int N=2e5+50,LIM=30;
map < pii,int > mp;
map < pii,int > mp_v;
int n,m;
int rk[N],val[N],anc[N];
int base[LIM+5],pos[LIM+5],top;
struct data {
int u,x,y,w,c;
data(int u,int x,int y,int w,int c):u(u),x(x),y(y),w(w),c(c){}
friend inline bool operator <(const data &a,const data &b) {return a.u<b.u;}
};
vector <data> qry[N*4];
inline void insert(int k,int l,int r,int L,int R,const data &t) {
if(L<=l&&r<=R) {qry[k].push_back(t); return;}
int mid=(l+r)>>1;
if(R<=mid) insert(k<<1,l,mid,L,R,t);
else if(L>mid) insert(k<<1|1,mid+1,r,L,R,t);
else insert(k<<1,l,mid,L,R,t),insert(k<<1|1,mid+1,r,L,R,t);
}
inline pii getanc(int x) {
int rs=0;
while(x!=anc[x]) rs^=val[x],x=anc[x];
return make_pair(x,rs);
}
inline int inc(int x) {
for(int i=LIM;~i;i--) if(pos[i] && (x&(1<<i))) x^=base[pos[i]];
for(int i=LIM;~i;i--) if(!pos[i] && (x&(1<<i))) {
base[++top]=x; pos[i]=top;
return i;
} return -1;
}
inline int query(int x,int y) {
x=getanc(x).second^getanc(y).second;
for(int i=LIM;~i;i--) if(pos[i] && (x&(1<<i))) x=x^base[pos[i]];
return x;
}
inline void dfs(int k,int l,int r) {
if(l==r) sort(qry[k].begin(),qry[k].end());
for(int i=0;i<qry[k].size();++i) {
data t=qry[k][i];
if(t.u==1) {
pii x=getanc(t.x),y=getanc(t.y);
if(x.first==y.first) {
int p=inc(x.second^y.second^t.w);
if(~p) qry[k][i].c=3+p;
} else {
if(rk[x.first]<rk[y.first]) swap(x,y);
anc[y.first]=x.first; val[y.first]=t.w^x.second^y.second;
if(rk[x.first]==rk[y.first]) ++rk[x.first],qry[k][i].c=2;
else qry[k][i].c=1;
qry[k][i].x=x.first,qry[k][i].y=y.first;
}
} else printf("%d\n",query(t.x,t.y));
}
if(l!=r) {
int mid=(l+r)>>1;
dfs(k<<1,l,mid);
dfs(k<<1|1,mid+1,r);
}
for(int i=qry[k].size()-1;i>=0;i--) {
data t=qry[k][i];
if(!t.c) continue;
if(t.c<=2) {
anc[t.y]=t.y; val[t.y]=0;
rk[t.x]-=(t.c-1);
} else {
pos[t.c-3]=0;
--top;
}
}
}
int main() {
n=rd(), m=rd();
for(int i=1;i<=n;i++) anc[i]=i;
for(int i=1;i<=m;i++) {
int x=rd(), y=rd(), w=rd();
if(x>y) swap(x,y);
mp[make_pair(x,y)]=0;
mp_v[make_pair(x,y)]=w;
}
m=rd();
for(int i=1;i<=m;i++) {
int op=rd(), x=rd(), y=rd();
if(x>y) swap(x,y);
if(op==1) {
int w=rd();
mp[make_pair(x,y)]=i;
mp_v[make_pair(x,y)]=w;
} else if(op==2) {
int pre=mp[make_pair(x,y)],w=mp_v[make_pair(x,y)];
mp.erase(mp.find(make_pair(x,y)));
mp_v.erase(mp_v.find(make_pair(x,y)));
insert(1,0,m,pre,i,data(1,x,y,w,0));
} else insert(1,0,m,i,i,data(2,x,y,0,0));
}
for(map< pair<int,int>,int >::iterator it=mp.begin(),it2=mp_v.begin();it!=mp.end();++it,++it2)
insert(1,0,m,it->second,m,data(1,it->first.first,it->first.second,it2->second,0));
dfs(1,0,m);
}