Description
现在,我想知道自己是否还有选择。
给定n个点m条边的无向图以及顺序发生的q个事件。
每个事件都属于下面两种之一:
1、删除某一条图上仍存在的边
2、询问是否存在两条边不相交的路径可以从点u出发到点v
Solution
我可能是个SB……
其实我以前还做过这题,BZOJ的星球联盟,但是我忘了,想的做法是类似BZOJ1969的。
正常的做法是倒着加边,然后把树上的一段点缩成一个,用LCT或并查集维护。
我的做法也是倒着加边,两点没有连通就连起来,已连通就把两点路径上的边都打上标记,询问输出Yes就是两点路径上的边都被打标记,其实本质好像是一样的。
询问如果是同一个点不知道怎么搞,数据好像也没有……那不管了……
Code
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define pa pair<int,int>
const int Maxn=100010;
const int inf=2147483647;
const int mod=1001001;
int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
return x*f;
}
int n,m,q,rt[Maxn],_rt[Maxn],fa[Maxn],dfn[Maxn],DFN=0,son[Maxn],dep[Maxn],sz[Maxn],top[Maxn];bool mark[Maxn];
int findrt(int x){return((rt[x]==x)?x:rt[x]=findrt(rt[x]));}
struct Edge{int y,next;}e[Maxn<<2];int last[Maxn],len=0;
void ins(int x,int y){int t=++len;e[t].y=y;e[t].next=last[x];last[x]=t;}
struct Seg{int l,r,lc,rc,c;}tr[Maxn<<1];int tot=0;
void Modify(int x){tr[x].c=true;}
void up(int x){tr[x].c=tr[tr[x].lc].c&tr[tr[x].rc].c;}
void down(int x){if(tr[x].c)Modify(tr[x].lc),Modify(tr[x].rc);}
void build(int l,int r)
{
int x=++tot;tr[x].l=l;tr[x].r=r;tr[x].c=false;
if(l==r)return;
int mid=l+r>>1;
tr[x].lc=tot+1,build(l,mid);
tr[x].rc=tot+1,build(mid+1,r);
up(x);
}
void modify(int x,int l,int r)
{
if(l>r)return;
if(tr[x].l==l&&tr[x].r==r){Modify(x);return;}
int mid=tr[x].l+tr[x].r>>1,lc=tr[x].lc,rc=tr[x].rc;
down(x);
if(r<=mid)modify(lc,l,r);
else if(l>mid)modify(rc,l,r);
else modify(lc,l,mid),modify(rc,mid+1,r);
up(x);
}
bool query(int x,int l,int r)
{
if(l>r)return true;
if(tr[x].l==l&&tr[x].r==r)return tr[x].c;
int mid=tr[x].l+tr[x].r>>1,lc=tr[x].lc,rc=tr[x].rc;
down(x);
if(r<=mid)return query(lc,l,r);
if(l>mid)return query(rc,l,r);
return(query(lc,l,mid)&query(rc,mid+1,r));
}
struct Opt{int type,x,y;}Q[Maxn];int ans[Maxn],la=0;
struct edge{int x,y;edge(int _x=0,int _y=0){x=_x,y=_y;}}rest[Maxn],tmp[Maxn];int lr=0,lt=0;
bool operator<(edge a,edge b)
{
if(a.x!=b.x)return a.x<b.x;
return a.y<b.y;
}
priority_queue<edge>q1,q2;
void dfs1(int x,int ff)
{
fa[x]=ff;dep[x]=dep[ff]+1;son[x]=0;sz[x]=1;
for(int i=last[x];i;i=e[i].next)
{
int y=e[i].y;
if(y==ff)continue;
dfs1(y,x);sz[x]+=sz[y];
if(sz[y]>sz[son[x]])son[x]=y;
}
}
void dfs2(int x,int Top)
{
top[x]=Top;dfn[x]=++DFN;
if(son[x])dfs2(son[x],Top);
for(int i=last[x];i;i=e[i].next)
{
int y=e[i].y;
if(y==son[x]||y==fa[x])continue;
dfs2(y,y);
}
}
bool w(int x,int y,int o)
{
int tx=top[x],ty=top[y];bool re=true;
while(tx!=ty)
{
if(dep[tx]<dep[ty])swap(x,y),swap(tx,ty);
if(o==0)modify(1,dfn[tx],dfn[x]);
else re&=query(1,dfn[tx],dfn[x]);
x=fa[tx];tx=top[x];
}
if(dep[x]<dep[y])swap(x,y);
if(o==0)modify(1,dfn[son[y]],dfn[x]);
else re&=query(1,dfn[son[y]],dfn[x]);
return re;
}
int main()
{
n=read(),m=read(),q=read();dfn[0]=inf;
for(int i=1;i<=n;i++)rt[i]=i;
for(int i=1;i<=m;i++)
{
int x=read(),y=read();
if(x>y)swap(x,y);q1.push(edge(x,y));
}
for(int i=1;i<=q;i++)
{
char op[2];
scanf("%s",op);
if(op[0]=='P')Q[i].type=1;else Q[i].type=0;
int x=read(),y=read();
if(x>y)swap(x,y);Q[i].x=x,Q[i].y=y;
if(Q[i].type==0)q2.push(edge(x,y));
}
while(!q1.empty())
{
edge t1=q1.top();q1.pop();
if(q2.empty())rest[++lr]=t1;
else
{
edge t2=q2.top();
if(t1.x==t2.x&&t1.y==t2.y)q2.pop();
else rest[++lr]=t1;
}
}
for(int i=1;i<=lr;i++)
{
int fx=findrt(rest[i].x),fy=findrt(rest[i].y);
if(fx==fy){tmp[++lt]=rest[i];continue;}
rt[fx]=fy;ins(rest[i].x,rest[i].y),ins(rest[i].y,rest[i].x);
}
for(int i=1;i<=n;i++)_rt[i]=rt[i];
for(int i=q;i;i--)
if(Q[i].type==0)
{
int fx=findrt(Q[i].x),fy=findrt(Q[i].y);
if(fx==fy)continue;
rt[fx]=fy;ins(Q[i].x,Q[i].y),ins(Q[i].y,Q[i].x);
}
int root=n+1;
for(int i=1;i<=n;i++)
{
int t=findrt(i);
if(!mark[t])ins(root,t),mark[t]=true;
}
dep[0]=-1;dfs1(root,0);dfs2(root,root);
for(int i=1;i<=n;i++)rt[i]=_rt[i];
build(1,DFN);
for(int i=1;i<=lt;i++)w(tmp[i].x,tmp[i].y,0);
for(int i=q;i;i--)
{
int fx=findrt(Q[i].x),fy=findrt(Q[i].y);
if(Q[i].type==1)
{
if(fx!=fy)ans[++la]=0;
else ans[++la]=w(Q[i].x,Q[i].y,1);
}
else
{
if(fx!=fy)rt[fx]=fy;
else w(Q[i].x,Q[i].y,0);
}
}
for(int i=la;i;i--)puts(ans[i]==1?"Yes":"No");
}