bzoj4229 选择
Posted iefnah06
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj4229 选择相关的知识,希望对你有一定的参考价值。
URL
https://www.lydsy.com/JudgeOnline/problem.php?id=4229
简要题意
给一个无向图。
多次询问,每次删掉一条边,或者询问两个点是否在同一个边双连通分量内。
解法
倒着做。
先只保留所有操作结束后剩下的边,建出边双连通分量对应的森林。
然后倒序加边,每次要么是合并两个树,要么是把一条路径上的点都缩到同一个双连通分量里。
实现
#include <bits/stdc++.h>
using namespace std;
#define rng(i,a,b) for(int i=int(a);i<int(b);i++)
#define gnr(i,a,b) for(int i=int(b)-1;i>=int(a);i--)
#define rep(i,b) rng(i,0,b)
#define per(i,b) gnr(i,0,b)
#define pb push_back
#define mp make_pair
#define a first
#define b second
#define all(x) (x).begin(),(x).end()
#define si(x) int((x).size())
typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
typedef pair<int,int> pi;
typedef vector<int> vi;
template<class t,class u> void chmax(t&a,u b){if(a<b)a=b;}
template<class t,class u> void chmin(t&a,u b){if(b<a)a=b;}
struct unionfind{
vi p;
unionfind(int n=0):p(n,-1){}
int find(int a){
return p[a]<0?a:(p[a]=find(p[a]));
}
void mg(int a,int b){
a=find(a);
b=find(b);
if(a!=b)p[a]=b;
}
bool same(int a,int b){
return find(a)==find(b);
}
};
const int vmax=1.1e5;
struct Q{
char tp;
int x,y;
friend istream&operator>>(istream&i,Q&q){
i>>q.tp>>q.x>>q.y;
q.x--,q.y--;
if(q.x>q.y)swap(q.x,q.y);
return i;
}
};
struct E{
int s;
bool tp;
E(){}
E(int a,int b,bool t):s(a^b),tp(t){}
int other(int a){
return a^s;
}
};
Q qs[vmax];
unionfind u1,u2;
vector<E> info;
vi g[vmax];
int ce=0;
void make(int a,int b,bool t){
g[a].pb(si(info));
g[b].pb(si(info));
info.pb(E(a,b,t));
}
int id[vmax],lo[vmax],cur;
int par[vmax],dep[vmax];
int res[vmax];
void dfs(int v,int p){
id[v]=lo[v]=cur++;
rep(z,si(g[v])){
int e=g[v][z];
if(e==p)continue;
int to=info[e].other(v);
bool tp=info[e].tp;
if(id[to]==-1){
dep[to]=dep[v]+1;
par[to]=v;
dfs(to,e);
if(!tp){
chmin(lo[v],lo[to]);
if(lo[to]<=id[v])u2.mg(to,v);
}
}else if(!tp){
chmin(lo[v],id[to]);
}
}
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
int n,m,q;cin>>n>>m>>q;
multiset<pi> es;
rep(i,m){
int a,b;cin>>a>>b;
a--,b--;
if(a>b)swap(a,b);
es.insert(pi(a,b));
}
rep(i,q){
cin>>qs[i];
if(qs[i].tp=='Z')
es.erase(es.find(pi(qs[i].x,qs[i].y)));
}
u1=unionfind(n);
u2=unionfind(n);
{
for(multiset<pi>::iterator it=es.begin();it!=es.end();++it){
int a=it->a,b=it->b;
u1.mg(a,b);
make(a,b,false);
}
unionfind tmp=u1;
gnr(i,0,q)if(qs[i].tp=='Z'){
int a=qs[i].x,b=qs[i].y;
if(tmp.same(a,b))continue;
tmp.mg(a,b);
make(a,b,true);
}
fill(id,id+n,-1);
fill(par,par+n,-1);
rep(i,n)if(id[i]==-1)dfs(i,-1);
assert(n==cur);
}
gnr(i,0,q){
int a=qs[i].x,b=qs[i].y;
if(qs[i].tp=='Z'){
if(!u1.same(a,b)){
if(dep[a]<dep[b])swap(a,b);
u1.mg(a,b);
}else{
while(true){
a=u2.find(a);
b=u2.find(b);
if(a==b)break;
if(dep[a]<dep[b])swap(a,b);
u2.mg(a,par[a]);
a=par[a];
}
}
}else{
res[i]=u2.same(a,b);
}
}
rep(i,q)if(qs[i].tp=='P'){
cout<<(res[i]?"Yes":"No")<<'
';
}
}
以上是关于bzoj4229 选择的主要内容,如果未能解决你的问题,请参考以下文章