zoukankan      html  css  js  c++  java
  • 【BZOJ4025】二分图 LCT

    【BZOJ4025】二分图

    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。

    题解:感觉cdq分治过于高端,LCT比较好想~

    我们希望这样一个集合(本质是数组),保存的是当前时刻,所有加入之后会形成奇环的非树边。如果当前时刻集合中有元素,则不是一个二分图。那么删边的时候如何处理呢?如果我们删的是一条树边,那么假如集合中存在一条覆盖这条树边的非树边,那么这条非树边就会变成新的树边。这样的情况很难处理,所以我们希望保证:所有已经进入集合的非树边都不会从集合中出来再次成为树边,即,我们要维护的是关于删除时间的最大生成树。可以用LCT搞定。

    然后就没啦~我在link的时候手残连的是实边,居然也过了~

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    const int maxn=500010;
    int n,m,T,tot,sum;
    int vis[maxn];
    struct LCT
    {
    	int ch[2],fa,v,sm,rev,siz;
    }s[maxn];
    struct edge
    {
    	int pa,pb,t1,t2;
    }p[maxn];
    struct operate
    {
    	int tim,op,org;
    }q[maxn];
    bool cmp(operate a,operate b)
    {
    	return (a.tim==b.tim)?(a.op>b.op):(a.tim<b.tim);
    }
    bool isr(int x)	{return s[s[x].fa].ch[0]!=x&&s[s[x].fa].ch[1]!=x;}
    int MN(int a,int b)
    {
    	return s[a].v<s[b].v?a:b;
    }
    void pushup(int x)
    {
    	s[x].siz=s[s[x].ch[0]].siz+s[s[x].ch[1]].siz+1;
    	s[x].sm=MN(x,MN(s[s[x].ch[0]].sm,s[s[x].ch[1]].sm));
    }
    void pushdown(int x)
    {
    	if(s[x].rev)
    	{
    		swap(s[x].ch[0],s[x].ch[1]);
    		if(s[x].ch[0])	s[s[x].ch[0]].rev^=1;
    		if(s[x].ch[1])	s[s[x].ch[1]].rev^=1;
    		s[x].rev=0;
    	}
    }
    void updata(int x)
    {
    	if(!isr(x))	updata(s[x].fa);
    	pushdown(x);
    }
    void rotate(int x)
    {
    	int y=s[x].fa,z=s[y].fa,d=(x==s[y].ch[1]);
    	if(!isr(y))	s[z].ch[y==s[z].ch[1]]=x;
    	s[x].fa=z,s[y].fa=x,s[y].ch[d]=s[x].ch[d^1];
    	if(s[x].ch[d^1])	s[s[x].ch[d^1]].fa=y;
    	s[x].ch[d^1]=y;
    	pushup(y),pushup(x);
    }
    void splay(int x)
    {
    	updata(x);
    	while(!isr(x))
    	{
    		int y=s[x].fa,z=s[y].fa;
    		if(!isr(y))
    		{
    			if((x==s[y].ch[1])^(y==s[z].ch[1]))	rotate(x);
    			else	rotate(y);
    		}
    		rotate(x);
    	}
    }
    void access(int x)
    {
    	for(int y=0;x;splay(x),s[x].ch[1]=y,pushup(x),y=x,x=s[x].fa);
    }
    void maker(int x)
    {
    	access(x),splay(x),s[x].rev^=1;
    }
    void link(int x,int y)	//x上
    {
    	//printf("l %d %d
    ",x,y);
    	access(x),splay(x),maker(y);
    	s[x].ch[1]=y,s[y].fa=x,pushup(x);
    }
    void cut(int x,int y)
    {
    	//printf("c %d %d
    ",x,y);
    	maker(x),access(y),splay(y);
    	s[y].ch[0]=s[x].fa=0,pushup(y);
    }
    int findr(int x)
    {
    	access(x),splay(x);
    	while(s[x].ch[0])	x=s[x].ch[0];
    	return x;
    }
    int rd()
    {
    	int ret=0,f=1;	char gc=getchar();
    	while(gc<'0'||gc>'9')	{if(gc=='-')f=-f;	gc=getchar();}
    	while(gc>='0'&&gc<='9')	ret=ret*10+gc-'0',gc=getchar();
    	return ret*f;
    }
    int main()
    {
    	n=rd(),m=rd(),T=rd();
    	int i,j,a,b,c,d;
    	for(i=0;i<=n;i++)	s[i].v=1<<30;
    	for(i=1;i<=m;i++)
    	{
    		p[i].pa=rd(),p[i].pb=rd(),q[i].tim=p[i].t1=rd(),s[i+n].v=q[i+m].tim=p[i].t2=rd();
    		s[i+n].siz=1,s[i+n].sm=i+n;
    		q[i].org=q[i+m].org=i,q[i].op=1,q[i+m].op=0;
    	}
    	sort(q+1,q+2*m+1,cmp);
    	for(i=j=1;i<=T;i++)
    	{
    		for(;j<=2*m&&q[j].tim<i;j++)
    		{
    			a=p[q[j].org].pa,b=p[q[j].org].pb,c=q[j].org+n;
    			if(q[j].op)
    			{
    				if(findr(a)!=findr(b))	link(a,c),link(b,c);
    				else
    				{
    					maker(a),access(b),splay(b),d=s[b].sm;
    					if((s[b].siz+1)&2)
    					{
    						sum++;
    						if(s[d].v<s[c].v)	cut(d,p[d-n].pa),cut(d,p[d-n].pb),link(a,c),link(b,c),vis[d]=1;
    						else	vis[c]=1;
    					}
    					else
    					{
    						if(s[d].v<s[c].v)	cut(d,p[d-n].pa),cut(d,p[d-n].pb),link(a,c),link(b,c),vis[d]=2;
    						else	vis[c]=2;
    					}
    				}
    			}
    			else
    			{
    				if(!vis[c])	cut(c,a),cut(c,b);
    				if(vis[c]==1)	sum--;
    			}
    		}
    		if(sum)	printf("No
    ");
    		else	printf("Yes
    ");
    	}
    	return 0;
    }
  • 相关阅读:
    Linux平台下基于图像识别的自动化测试-sikuli环境搭建
    从命令行运行SikuliX
    Linux命令grep过滤的用法
    PyCharm注释头模板
    从BeautifulReport生成的html格式的测试报告中获取测试结果,并写入到一个表格中
    unittest在命令行中执行
    在Debian上安装Docker Engine
    Linux平台UI自动化测试-环境搭建
    python标准库smtplib在UI自动化测试中的实现-邮件发送测试报告
    wget cooikes 下载
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/7149018.html
Copyright © 2011-2022 走看看