Description
现在,我想知道自己是否还有选择。
给定n个点m条边的无向图以及顺序发生的q个事件。
每个事件都属于下面两种之一:
1、删除某一条图上仍存在的边
2、询问是否存在两条边不相交的路径可以从点u出发到点v
对于全部数据,max(n,m,q)<=100000
Solution
考虑离线变成加边,那么就是在一个环内的两点是Yes。用LCT和并查集维护加边动态求连通分量即可
Code
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <vector>
#include <stack>
#include <map>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)
#define drp(i,st,ed) for (int i=st;i>=ed;--i)
const int N=200005;
const int E=400005;
struct edge {int x,y,next;} e[E],q[N];
struct LCT {
struct treeNode {int son[2],fa,rev,is_root;} t[N];
int fa[N];
LCT() {rep(i,1,N-1) fa[i]=i,t[i].is_root=1;}
int find(int x) {
return (fa[x]==x)?x:(fa[x]=find(fa[x]));
}
void push_down(int x) {
if (!t[x].rev) return ; t[x].rev=0;
std:: swap(t[x].son[0],t[x].son[1]);
if (t[x].son[0]) t[t[x].son[0]].rev^=1;
if (t[x].son[1]) t[t[x].son[1]].rev^=1;
}
void rotate(int x) {
if (t[x].is_root) return ;
int y=find(t[x].fa); int z=find(t[y].fa);
int k=t[y].son[1]==x;
t[y].son[k]=t[x].son[!k];
if (t[x].son[!k]) t[t[x].son[!k]].fa=y;
t[x].son[!k]=y; t[y].fa=x;
t[x].fa=z;
if (t[y].is_root) {
t[x].is_root=1;
t[y].is_root=0;
} else t[z].son[t[z].son[1]==y]=x;
}
void remove(int x) {
if (!t[x].is_root) remove(t[x].fa);
push_down(x);
}
void splay(int x) {
remove(x);
for (;!t[x].is_root;) {
int y=find(t[x].fa); int z=find(t[y].fa);
if (!t[y].is_root) {
if ((t[y].son[1]==x)^(t[z].son[1]==y)) rotate(x);
else rotate(y);
}
rotate(x);
}
}
void access(int x) {
for (int y=0;x;) {
splay(x);
t[t[x].son[1]].is_root=1;
t[t[x].son[1]=y].is_root=0;
y=x; x=find(t[x].fa);
}
}
void mroot(int x) {
x=find(x);
access(x); splay(x); t[x].rev^=1;
}
void link(int x,int y) {
x=find(x); y=find(y);
if (x==y) return ;
mroot(x); access(y); t[x].fa=y;
}
void dfs(int x,int rt) {
if (!x) return ;
fa[x]=rt;
dfs(t[x].son[0],rt);
dfs(t[x].son[1],rt);
}
void merge(int x,int y) {
x=find(x); y=find(y);
if (x==y) return ;
mroot(x); access(y); splay(x);
dfs(x,x);
}
} LCT;
std:: vector <edge> vec;
std:: map <int,bool> map[N];
std:: stack <int> ans;
int fa[N];
int read() {
int x=0,v=1; char ch=getchar();
for (;ch<'0'||ch>'9';v=(ch=='-')?(-1):(v),ch=getchar());
for (;ch<='9'&&ch>='0';x=x*10+ch-'0',ch=getchar());
return x*v;
}
int find(int x) {
return (fa[x]==x)?x:(fa[x]=find(fa[x]));
}
int main(void) {
freopen("data.in","r",stdin);
int n=read(),m=read(),T=read();
rep(i,1,n) fa[i]=i;
rep(i,1,m) vec.push_back((edge) {read(),read()});
rep(i,1,T) {
q[i].next=getchar();
for (;q[i].next!='Z'&&q[i].next!='P';) q[i].next=getchar();
q[i].x=read(),q[i].y=read();
if (q[i].next=='Z') {
map[q[i].x][q[i].y]=map[q[i].y][q[i].x]=true;
}
}
for (int i=0;i<vec.size();++i) {
edge e=vec[i];
if (!map[e.x][e.y]) {
if (find(e.x)!=find(e.y)) {
LCT.link(e.x,e.y);
fa[find(e.x)]=find(e.y);
} else {
LCT.merge(e.x,e.y);
}
}
}
drp(i,T,1) {
edge e=q[i];
if (q[i].next=='Z') {
if (find(e.x)!=find(e.y)) {
LCT.link(e.x,e.y);
fa[find(e.x)]=find(e.y);
} else {
LCT.merge(e.x,e.y);
}
} else {
if (find(e.x)!=find(e.y)) {
ans.push(0);
} else {
if (LCT.find(q[i].x)==LCT.find(q[i].y)) {
ans.push(1);
} else ans.push(0);
}
}
}
for (;!ans.empty();) {
int top=ans.top(); ans.pop();
top?puts("Yes"):puts("No");
}
return 0;
}