【刷题】BZOJ 4025 二分图

Description

神犇有一个n个节点的图。因为神犇是神犇,所以在T时间内一些边会出现后消失。神犇要求出每一时间段内这个图是否是二分图。这么简单的问题神犇当然会做了,于是他想考考你。

Input

输入数据的第一行是三个整数n,m,T。

第2行到第m+1行,每行4个整数u,v,start,end。第i+1行的四个整数表示第i条边连接u,v两个点,这条边在start时刻出现,在第end时刻消失。

Output

输出包含T行。在第i行中,如果第i时间段内这个图是二分图,那么输出“Yes”,否则输出“No”,不含引号。

Sample Input

3 3 3  
1 2 0 2  
2 3 0 3  
1 3 1 2

Sample Output

Yes  
No  
Yes

HINT

样例说明:

0时刻,出现两条边1-2和2-3。

第1时间段内,这个图是二分图,输出Yes。

1时刻,出现一条边1-3。

第2时间段内,这个图不是二分图,输出No。

2时刻,1-2和1-3两条边消失。

第3时间段内,只有一条边2-3,这个图是二分图,输出Yes。

数据范围:

n<=100000,m<=200000,T<=100000,1<=u,v<=n,0<=start<=end<=T。

Solution

首先看怎么静态判能不能二分,一条一条边加进去,如果这条边加上会变成一个环,并且这个环还是奇环,那就不能二分;反之,可以

然后看动态的,动态的麻烦就在删除,因为可能把一条树边删掉之后,会有一条非树边代替它变成一条树边,这个做不了;所以就弄一个LCT维护这个树,维护这个图以删除时间为关键字的最大生成树,这样就不会有上述情况发生了

然后按照套路,离线解决

(PS:从早上开始调,一直调到晚上,开始的时候造数据的程序还写错了,会使标程RE,然后有一次其实改对了,但因为数据造错,一直拍不上,结果就和gt拿了一个正确的程序调了半个小时)

#include<bits/stdc++.h>
#define ui unsigned int
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
const int MAXN=100000+10,MAXM=200000+10,inf=0x3f3f3f3f;
int n,m,tT,V[MAXN+MAXM],sum,f[MAXN+MAXM];
struct edge{
	int u,v;
};
edge side[MAXM];
struct data{
	int opt,val,t,id;
	inline bool operator < (const data &A) const {
		return t<A.t||t==A.t&&opt>A.opt;
	};
};
data p[MAXM<<1];
#define lc(x) ch[(x)][0]
#define rc(x) ch[(x)][1]
struct LCT{
	int ch[MAXN+MAXM][2],fa[MAXN+MAXM],rev[MAXN+MAXM],Mn[MAXN+MAXM],id[MAXN+MAXM],stack[MAXN+MAXM],cnt,val[MAXN+MAXM],size[MAXN+MAXM];
	inline void init()
	{
		memset(Mn,inf,sizeof(Mn));
		memset(val,inf,sizeof(val));
	}
	inline bool nroot(int x)
	{
		return lc(fa[x])==x||rc(fa[x])==x;
	}
	inline void reverse(int x)
	{
		std::swap(lc(x),rc(x));
		rev[x]^=1;
	}
	inline void pushup(int x)
	{
		size[x]=size[lc(x)]+size[rc(x)]+1;
		Mn[x]=val[x],id[x]=x;
		if(Mn[lc(x)]<Mn[x])Mn[x]=Mn[lc(x)],id[x]=id[lc(x)];
		if(Mn[rc(x)]<Mn[x])Mn[x]=Mn[rc(x)],id[x]=id[rc(x)];
	}
	inline void pushdown(int x)
	{
		if(rev[x])
		{
			if(lc(x))reverse(lc(x));
			if(rc(x))reverse(rc(x));
			rev[x]=0;
		}
	}
	inline void rotate(int x)
	{
		int f=fa[x],p=fa[f],c=(rc(f)==x);
		if(nroot(f))ch[p][rc(p)==f]=x;
		fa[ch[f][c]=ch[x][c^1]]=f;
		fa[ch[x][c^1]=f]=x;
		fa[x]=p;
		pushup(f);
		pushup(x);
	}
	inline void splay(int x)
	{
		cnt=0;
		stack[++cnt]=x;
		for(register int i=x;nroot(i);i=fa[i])stack[++cnt]=fa[i];
		while(cnt)pushdown(stack[cnt--]);
		for(register int y=fa[x];nroot(x);rotate(x),y=fa[x])
			if(nroot(y))rotate((lc(y)==x)==(lc(fa[y])==y)?y:x);
		pushup(x);
	}
	inline void access(int x)
	{
		for(register int y=0;x;x=fa[y=x])splay(x),rc(x)=y,pushup(x);
	}
	inline int findroot(int x)
	{
		access(x);splay(x);
		while(lc(x))pushdown(x),x=lc(x);
		splay(x);
		return x;
	}
	inline void makeroot(int x)
	{
		access(x);splay(x);reverse(x);
	}
	inline void split(int x,int y)
	{
		makeroot(x);access(y);splay(y);
	}
	inline void link(int x,int y)
	{
		makeroot(x);fa[x]=y;
	}
	inline void cut(int x,int y)
	{
		split(x,y);fa[x]=lc(y)=0;pushup(y);
	}
};
LCT T;
#undef lc
#undef rc
template<typename T> inline void read(T &x)
{
	T data=0,w=1;
	char ch=0;
	while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
	if(ch=='-')w=-1,ch=getchar();
	while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar();
	x=data*w;
}
template<typename T> inline void write(T x,char c='\0')
{
	if(x<0)putchar('-'),x=-x;
	if(x>9)write(x/10);
	putchar(x%10+'0');
	if(c!='\0')putchar(c);
}
template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);}
template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);}
template<typename T> inline T min(T x,T y){return x<y?x:y;}
template<typename T> inline T max(T x,T y){return x>y?x:y;}
inline void add(int now)
{
	int u=side[p[now].id].u,v=side[p[now].id].v,sn=p[now].id+n;
	if(u==v)
	{
		f[sn-n]=1;sum++;
		return ;
	}
	if(T.findroot(u)!=T.findroot(v))T.val[sn]=p[now].val,T.link(sn,u),T.link(sn,v),V[sn-n]=1;
	else
	{
		T.split(u,v);
		int so=T.id[v],nt=T.size[v]>>1;
		if(p[now].val>T.Mn[v])
		{
			if(!(nt&1))sum++,f[so-n]=1;
			T.cut(so,side[so-n].u);
			T.cut(so,side[so-n].v);
			T.val[sn]=p[now].val;
			T.link(sn,u);
			T.link(sn,v);
			V[so-n]=0;V[sn-n]=1;
		}
		else if(!(nt&1))sum++,f[sn-n]=1;
	}
}
inline void del(int now)
{
	int sn=p[now].id+n;
	sum-=f[sn-n];
	if(V[sn-n])
	{
		V[sn-n]=f[sn-n]=0;
		T.cut(sn,side[sn-n].u);T.cut(sn,side[sn-n].v);
	}
	else f[sn-n]=0;
}
int main()
{
	read(n);read(m);read(tT);
	for(register int i=1;i<=m;++i)
	{
		int u,v,st,ed;
		read(u);read(v);read(st);read(ed);
		side[i].u=u;side[i].v=v;
		p[i].t=st;p[i].val=ed;p[i].id=i;p[i].opt=1;
		p[i+m].t=ed;p[i+m].id=i;p[i+m].opt=0;
	}
	std::sort(p+1,p+m*2+1);
	T.init();
	for(register int i=1,j=1;i<=tT;++i)
	{
		for(;p[j].t<i&&j<=m*2;++j)
			if(p[j].opt)add(j);
			else del(j);
		if(sum)puts("No");
		else puts("Yes");
	}
	return 0;
}
posted @ 2018-04-08 21:24  HYJ_cnyali  阅读(168)  评论(0编辑  收藏  举报