CF813F Bipartite Checking

一、題目

點此看題

二、解法

把每條邊出現時間段打到線段樹上面,然後跑一遍線段樹。

問題在於維護一個樹的結構,如果一條邊連接的兩點暫時還不連通,我們就連接一波。否則我們看這條非樹邊構成的環是不是奇環,如果是的話直接不符合條件,否則沒有影響(這裏你需要考慮兩條非樹邊構成的環)

可以用啓發式合併的並查集,可以算一個點到根的距離的奇偶disdis,合併(u,v)(u,v)需要連接一條dis(u)dis(v)1dis(u)\oplus dis(v)\oplus 1,因爲我們是合併的根,你可以發現這樣構建的兩點距離是11 。回退的時候記錄一下哪兩個點合併,撤銷就很容易了。

#include <cstdio>
#include <iostream>
#include <vector>
#include <map>
using namespace std;
#define mk make_pair
#define pii pair<int,int>
const int M = 100005;
int read()
{	
	int x=0,flag=1;char c;
	while((c=getchar())<'0' || c>'9') if(c=='-') flag=-1;
	while(c>='0' && c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
	return x*flag;
}
int n,m,tp,dep[M],c[M],fa[M],st[2*M];
map<pii,int> mp;vector<pii> v[4*M];
int find(int x)
{
	return x==fa[x]?x:find(fa[x]);
}
int dis(int x)
{
	return x==fa[x]?0:(c[x]^dis(fa[x]));
}
void merge(int u,int v,int ct)
{
	if(dep[u]<dep[v]) swap(u,v);
	fa[v]=u;c[v]=ct;
	if(dep[u]==dep[v]) st[++tp]=-u,dep[u]++;
	st[++tp]=v;
}
void back(int t)
{
	while(tp>t)
	{
		if(st[tp]<0) dep[-st[tp]]--;
		else fa[st[tp]]=st[tp],c[st[tp]]=0;
		tp--;
	}
}
void ins(int i,int l,int r,int L,int R,pii x)
{
	if(l>R || L>r) return ;
	if(L<=l && r<=R)
	{
		v[i].push_back(x);
		return ;
	}
	int mid=(l+r)>>1;
	ins(i<<1,l,mid,L,R,x);
	ins(i<<1|1,mid+1,r,L,R,x);
}
void ask(int i,int l,int r)
{
	int cur=tp;
	for(int j=0;j<v[i].size();j++)
	{
		int x=v[i][j].first,y=v[i][j].second;
		int flag=dis(x)^dis(y)^1; 
		if(find(x)==find(y))
		{
			if(flag)
			{
				for(int i=l;i<=r;i++)
					puts("NO");
				back(cur);
				return ;
			}
		}
		else merge(find(x),find(y),flag);
	}
	if(l==r)
	{
		puts("YES");
		back(cur);
		return ;
	}
	int mid=(l+r)>>1;
	ask(i<<1,l,mid);
	ask(i<<1|1,mid+1,r);
	back(cur);
}
int main()
{
	n=read();m=read();
	for(int i=1;i<=n;i++)
		fa[i]=i;
	for(int i=1;i<=m;i++)
	{
		int u=read(),v=read();pii t=mk(u,v);
		if(mp.count(t))
			ins(1,1,m,mp[t],i-1,t),mp.erase(t);
		else mp[t]=i;
	}
	for(map<pii,int>::iterator it=mp.begin();it!=mp.end();it++)
		ins(1,1,m,it->second,m,it->first);
	ask(1,1,m);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章