http://www.elijahqi.win/archives/3238
Description
现在,我想知道自己是否还有选择。
给定n个点m条边的无向图以及顺序发生的q个事件。
每个事件都属于下面两种之一:
1、删除某一条图上仍存在的边
2、询问是否存在两条边不相交的路径可以从点u出发到点v
Input
第一行三个整数n,m,q
接下来m行,每行两个整数u,v,表示u和v之间有一条边
接下来q行,每行一个大写字母o和2个整数u、v,依次表示按顺序发生的q个事件:
当o为’Z’时,表示删除一条u和v之间的边
当o为’P’时,表示询问是否存在两条边不相交的路径可以从点u出发到点v
Output
对于每组询问,如果存在,输出Yes,否则输出No
Sample Input
7 8 7
1 2
1 3
1 4
2 3
3 4
3 7
7 4
5 6
Z 1 4
P 1 3
P 2 4
Z 1 3
P 1 3
Z 6 5
P 5 6
Sample Output
Yes
Yes
No
No
HINT
对于全部数据,max(n,m,q)<=100000
删边 不好做 改为离线 变成加边 然后动态维护边双联通分量即可
具体维护方法参见
https://blog.csdn.net/elijahqi/article/details/79327675
#include<map>
#include<queue>
#include<cstdio>
#include<cctype>
#include<algorithm>
#define pa pair<int,int>
using namespace std;
inline char gc(){
static char now[1<<16],*S,*T;
if (T==S){T=(S=now)+fread(now,1,1<<16,stdin);if (T==S) return EOF;}
return *S++;
}
inline int read(){
int x=0,f=1;char ch=gc();
while(!isdigit(ch)) {if (ch=='-') f=-1;ch=gc();}
while(isdigit(ch)) x=x*10+ch-'0',ch=gc();
return x*f;
}
const int N=1e5+10;
map<pa,int> mm;
map<pa,int>:: iterator it;
int fa[N],fa1[N],fa2[N],n,m,Q,c[N][2],q[N],top,cnt;bool rev[N];
inline int find1(int x){
while(x!=fa1[x]) x=fa1[x]=fa1[fa1[x]];return x;
}
inline int find2(int x){
while(x!=fa2[x]) x=fa2[x]=fa2[fa2[x]];return x;
}
inline bool isroot(int x){
return c[find2(fa[x])][0]!=x&&c[find2(fa[x])][1]!=x;
}
inline void pushdown(int x){
if (!rev[x]) return;rev[x]^=1;int l=c[x][0],r=c[x][1];
rev[l]^=1;rev[r]^=1;swap(c[x][0],c[x][1]);
}
inline void rotate(int x){
int y=find2(fa[x]),z=find2(fa[y]),l=c[y][1]==x,r=l^1;
if (!isroot(y)) c[z][c[z][1]==y]=x;
fa[c[x][r]]=y;fa[y]=x;fa[x]=z;
c[y][l]=c[x][r];c[x][r]=y;
}
inline void splay(int x){
q[top=1]=x;for (int i=x;!isroot(i);i=find2(fa[i]))
q[++top]=find2(fa[i]);
while(top) pushdown(q[top--]);
while(!isroot(x)){
int y=find2(fa[x]),z=find2(fa[y]);
if (!isroot(y)){
if (c[y][0]==x^c[z][0]==y) rotate(x);else rotate(y);
}rotate(x);
}
}
inline void access(int x){
for (int t=0;x;t=x,x=find2(fa[x])) splay(x),c[x][1]=t;
}
inline void makeroot(int x){
access(x);
splay(x);
rev[x]^=1;
}
inline void link(int x,int y){
fa1[find1(x)]=find1(y);
makeroot(x);fa[x]=y;
}
inline void dfs(int x,int f){
fa2[x]=f;if (c[x][0]) dfs(c[x][0],f);if (c[x][1]) dfs(c[x][1],f);
}
inline void insert1(int x,int y){
x=find2(x);y=find2(y);if (x==y) return;
if (find1(x)!=find1(y)) {link(x,y);return;}
makeroot(x);
access(y);
splay(y);
dfs(c[y][0],y);
}
struct node{int x,y,op,id;}qr[N];// op=0? print:del
bool ans[N];
int main(){
freopen("bzoj4229.in","r",stdin);
n=read();m=read();Q=read();
for (int i=1;i<=n;++i) fa1[i]=fa2[i]=i;
for (int i=1;i<=m;++i){
static int x,y;x=read();y=read();
if (x>y) swap(x,y);++mm[make_pair(x,y)];
}
for (int i=1;i<=Q;++i){
static char ch;static int x,y;
ch=gc();while(ch!='Z'&&ch!='P') ch=gc();
if (ch=='P')qr[i].x=read(),qr[i].y=read(),qr[i].op=0,qr[i].id=++cnt;
else{
x=read();y=read();if (x>y) swap(x,y);--mm[make_pair(x,y)];
qr[i].op=1;qr[i].x=x;qr[i].y=y;
}
}
for (it=mm.begin();it!=mm.end();++it){static int tim,x,y;
tim=it->second;x=it->first.first;y=it->first.second;
// printf("%d %d %d\n",tim,x,y);
for (int j=1;j<=tim;++j) insert1(x,y);
}
// printf("%d %d %d\n",find2(3),find2(4),find2(7));
for (int i=Q;i;--i){
if (!qr[i].op) ans[qr[i].id]=(find2(qr[i].x)==find2(qr[i].y));
else insert1(qr[i].x,qr[i].y);
}
for (int i=1;i<=cnt;++i) ans[i]?puts("Yes"):puts("No");
return 0;
}