[CF813F]Bipartite Checking

Bipartite Checking

題解

線段樹分治的板子題。

根據時間加邊與刪邊,如果直接維護這個圖的話明顯會T,當然只加邊的畫不會,但由於會刪邊,我們每次判圖都必須跑一遍這個圖,於是就需要O\left(nq),明顯會T,於是就要用線段樹分治來維護每個時間上的邊。

我們建一棵樹來維護每個時間的圖,從根到葉子的鏈上構成的圖就是葉子這個時間節點的圖的狀態。每次刪邊時,就在這條邊存在的時間區間上加上這條邊。這樣就可以維護任意時間點的圖,保證我們到任意點時只會有加邊的操作,不會去刪邊。

至於如何判斷二分圖,我們在點上都是維護了一個只有加邊動態圖的,如果回溯的話只需要撤銷最後加的那一條邊。我們用一個帶權並查集去維護這個圖,而並查集維護的圖又一定是一棵樹,而加一條邊是可以O\left(1 \right )解決的。爲了避免卡並查集,還需要按秩合併去保證樹高。

插入邊時若這條邊連接了兩棵未連接的樹,明顯不會有關係,可如果形成了奇環的話那就肯定不是二分圖了,而判奇環就只需要維護每個點的深度。

於是,就可以過這題了。

源碼

#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<bitset>
#include<stack>
#include<bits/stdc++.h>
using namespace std;
#define MAXN 200005
typedef long long LL;
#define lson rt<<1
#define rson rt<<1|1
typedef pair<int,int> pii;
template<typename _T>
void read(_T &x){
	_T f=1;x=0;char s=getchar();
	while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}
	while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=getchar();}
	x*=f;
}
template<typename _T>
_T Fabs(_T x){return x<0?-x:x;}
struct edge{int u,v;edge(int U,int V):u(U),v(V){}};
struct piar{int x,y;piar(int X,int Y):x(X),y(Y){}};
int n,q,L[MAXN<<2],R[MAXN<<2],ans[MAXN];
vector<edge> tag[MAXN<<2];
map<int,int> g[MAXN];
int fa[MAXN],siz[MAXN],dis[MAXN];
void build(int rt,int l,int r){
	L[rt]=l;R[rt]=r;if(l==r)return ;int mid=(l+r)>>1;
	build(lson,l,mid);build(rson,mid+1,r);
}
void query(int rt,int l,int r,const edge &E){
	if(L[rt]>r||R[rt]<l)return ;
	if(l<=L[rt]&&R[rt]<=r)return (void)(tag[rt].push_back(E));
	query(lson,l,r,E);query(rson,l,r,E);
}
int findFa(int x){while(fa[x]!=x)x=fa[x];return x;}
int getdis(int x){int res=0;while(fa[x]!=x)res^=dis[x],x=fa[x];return res;}
int solve(int x,int y,stack<piar> &sta){
	int dx=getdis(x),dy=getdis(y);
	x=findFa(x);y=findFa(y);
	if(x==y)return dx^dy;
	if(siz[x]>siz[y])swap(x,y),swap(dx,dy);
	siz[y]+=siz[x];fa[x]=y;dis[x]=dx^dy^1;
	sta.push(piar(x,y));return 1;
}
void delet(piar p){int x=p.x,y=p.y;siz[y]-=siz[x];dis[fa[x]=x]=0;} 
void dfs(int rt,int fg){
	stack<piar> sta;
	for(auto e:tag[rt])fg&=solve(e.u,e.v,sta);
	if(L[rt]==R[rt])ans[L[rt]]=fg;
	else dfs(lson,fg),dfs(rson,fg);
	while(!sta.empty()){delet(sta.top());sta.pop();}
}
signed main(){
	read(n);read(q);build(1,1,q);
	for(int i=1;i<=q;i++){
		int x,y;read(x);read(y);
		if(!g[x][y])g[x][y]=i;
		else query(1,g[x][y],i-1,edge(x,y)),g[x][y]=0;
	}
	for(int i=1;i<=n;i++){
		siz[fa[i]=i]=1;
		for(auto p:g[i])if(p.second>0)
			query(1,p.second,q,edge(i,p.first));
	}
	dfs(1,1);
	for(int i=1;i<=q;i++)puts(ans[i]?"YES":"NO");
	return 0;
}

謝謝!!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章