【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。
Source
能够考虑用LCT维护一个以删除时间为关键字的最大生成树 
同一时候维护一个边的集合表示在这个集合中的边假设在图中则一定不是二分图(就用一个数组就好了_ (:зゝ∠) _) 
由二分图的定义可知 二分图是没有奇环的图 
然后对于那两种操作: 
对于插入,假设边的两端点不连通,连边后一定不会形成环,直接link上 
假设已经联通,加边后一定存在非树边.此时假设加边后会形成奇环,就把这条边增加上述集合 
删除时候对于树边直接删除,非树边在集合中则直接从集合中删除
事实上也能够用cdq+并查集来搞 
详细做法没考虑过可是能够看Po姐姐的Blog 
PoPoQQQ
P.S.颓了那么久最终開始干正事了..
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define MAXN 100010
#define GET (ch>='0'&&ch<='9')
#define MAXINT 0x3f3f3f3f
using namespace std;
int n,m,T,Top,cnt;
int sta[MAXN<<1],top;
int In[MAXN<<1],on[MAXN<<1];
struct splay
{
    int ch[2],fa,minn,st,sum,val;
    bool rev;
}tree[MAXN<<2];
inline void in(int &x)
{
    char ch=getchar();x=0;
    while (!GET)    ch=getchar();
    while (GET) x=x*10+ch-'0',ch=getchar();
}
struct edge
{
    int u,v,w;
}e[MAXN<<1];
struct Edge
{
    int to;
    Edge *next;
}E[MAXN<<2],*prev1[MAXN],*prev2[MAXN];
inline void insert1(int u,int v)    {E[++Top].to=v;E[Top].next=prev1[u];prev1[u]=&E[Top];}
inline void insert2(int u,int v)    {E[++Top].to=v;E[Top].next=prev2[u];prev2[u]=&E[Top];}
inline bool is_root(int x)
{
    return tree[tree[x].fa].ch[0]!=x&&tree[tree[x].fa].ch[1]!=x;
}
inline void push_down(int x)
{
    if (tree[x].rev)
    {
        tree[tree[x].ch[0]].rev^=1,tree[tree[x].ch[1]].rev^=1;
        swap(tree[x].ch[0],tree[x].ch[1]);
    }
    tree[x].rev=0;
}
inline void push_up(int x)
{
    tree[x].minn=tree[x].val;tree[x].st=x;tree[x].sum=x>n;
    if (tree[x].ch[0])
    {
        if (tree[tree[x].ch[0]].minn<tree[x].minn)  tree[x].minn=tree[tree[x].ch[0]].minn,tree[x].st=tree[tree[x].ch[0]].st;
        tree[x].sum+=tree[tree[x].ch[0]].sum;
    }
    if (tree[x].ch[1])
    {
        if (tree[tree[x].ch[1]].minn<tree[x].minn)  tree[x].minn=tree[tree[x].ch[1]].minn,tree[x].st=tree[tree[x].ch[1]].st;
        tree[x].sum+=tree[tree[x].ch[1]].sum;
    }
}
inline void rot(int x)
{
    int y=tree[x].fa,z=tree[y].fa,l,r;
    l=(tree[y].ch[1]==x);r=l^1;
    if (!is_root(y))    tree[z].ch[tree[z].ch[1]==y]=x;
    tree[tree[x].ch[r]].fa=y;tree[y].fa=x;tree[x].fa=z;
    tree[y].ch[l]=tree[x].ch[r];tree[x].ch[r]=y;
    push_up(y);push_up(x);
}
inline void Splay(int x)
{
    top=0;sta[++top]=x;
    for (int i=x;!is_root(i);i=tree[i].fa)  sta[++top]=tree[i].fa;
    while (top) push_down(sta[top--]);
    while (!is_root(x))
    {
        int y=tree[x].fa,z=tree[y].fa;
        if (!is_root(y))
        {
            if ((tree[y].ch[0]==x)^(tree[z].ch[0]==y))  rot(x);
            else    rot(y);
        }
        rot(x);
    }
}
inline void access(int x)
{
    for (int i=0;x;i=x,x=tree[x].fa)    Splay(x),tree[x].ch[1]=i,push_up(x);
}
inline void make_root(int x)
{
    access(x);Splay(x);tree[x].rev^=1;
}
inline void link(int x,int y)
{
    make_root(x);tree[x].fa=y;
}
inline void cut(int x,int y)
{
    make_root(x);access(y);Splay(y);tree[y].ch[0]=tree[x].fa=0;push_up(y);
}
inline void split(int x,int y)
{
    make_root(x);access(y);Splay(y);
}
inline int find_root(int x)
{
    /*access(x);Splay(x);
    while (tree[x].ch[0])   x=tree[x].ch[0];*/
    for (access(x),Splay(x);tree[x].ch[0];x=tree[x].ch[0]);
    return x;
}
inline void ins(int x)
{
    int u=e[x].u,v=e[x].v;
    if (u==v)   {In[x]=1;cnt++;return;}
    if (find_root(u)!=find_root(v)) on[x]=1,link(u,x+n),link(v,x+n);
    else
    {
        split(u,v);int y=tree[v].st-n;
        if (e[y].w<e[x].w)
        {
            if (tree[v].sum&1^1)    In[y]=1,cnt++;
            cut(e[y].u,y+n);cut(e[y].v,y+n);link(u,x+n);link(v,x+n);
            on[y]=0;on[x]=1;
        }
        else
        if (tree[v].sum&1^1)    In[x]=1,cnt++;
    }
}
inline void del(int x)
{
    if (on[x])  cut(e[x].u,x+n),cut(e[x].v,x+n);
    else    if (In[x])  cnt--;
}
int main()
{
    in(n);in(m);in(T);int s,t;
    for (int i=1;i<=n;i++)  tree[i].val=tree[i].minn=MAXINT,tree[i].st=i;
    for (int i=1;i<=m;i++)
    {
        in(e[i].u);in(e[i].v);in(s);in(t);e[i].w=t;
        insert1(s,i);insert2(t,i);
        tree[i+n].val=tree[i+n].minn=t;tree[i+n].st=i+n;tree[i+n].sum=1;
    }
    for (int x=0;x<T;x++)
    {
        for (Edge *i=prev1[x];i;i=i->next)  ins(i->to);
        for (Edge *i=prev2[x];i;i=i->next)  del(i->to);
        puts(cnt?"No":"Yes");
    }
}
【BZOJ4025】二分图的更多相关文章
- BZOJ4025 二分图     分治 并查集 二分图 带权并查集按秩合并
		
原文链接http://www.cnblogs.com/zhouzhendong/p/8683831.html 题目传送门 - BZOJ4025 题意 有$n$个点,有$m$条边.有$T$个时间段.其中 ...
 - BZOJ4025 二分图(线段树分治+并查集)
		
之前学了一下线段树分治,这还是第一次写.思想其实挺好理解,即离线后把一个操作影响到的时间段拆成线段树上的区间,并标记永久化.之后一块处理,对于某个节点表示的时间段,影响到他的就是该节点一直到线段树根的 ...
 - [BZOJ4025]二分图(线段树分治,并查集)
		
4025: 二分图 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 2191 Solved: 800[Submit][Status][Discuss] ...
 - [bzoj4025]二分图_LCT
		
二分图 bzoj-4025 题目大意:给定一个n个节点的图,m条边,每条边有一个产生时间和一个删除时间,询问所有时间点是否是连通图. 注释:$1\le n\le 10^5$,$1\le m\le 2\ ...
 - bzoj4025 二分图
		
支持加边和删边的二分图判定,分治并查集水之(表示我的LCT还很不熟--仅仅停留在极其简单的模板水平). 由于是带权并查集,并且不能路径压缩,所以对权值(到父亲距离的奇偶性)的维护要注意一下. 有一个小 ...
 - bzoj4025二分图(线段树分治 并查集)
		
/* 思维难度几乎没有, 就是线段树分治check二分图 判断是否为二分图可以通过维护lct看看是否链接出奇环 然后发现不用lct, 并查集维护奇偶性即可 但是复杂度明明一样哈 */ #include ...
 - bzoj4025 二分图 [分治,并查集]
		
传送门 思路 是二分图的充要条件:图没有奇环. 考虑按时间分治,用可撤销并查集维护点到根的距离. 仍然可以用一个小trick把两点连边变成根连边,可以看这里. 每次连边时若不连通则连上,否则判一下有没 ...
 - bzoj4025: 二分图  lct
		
题意:带增删边的查询二分图 题解:因为二分图肯定带奇环,lct维护,每次要加入一条边之前判断会不会构成环,如果会就把最先会删除的边删掉,然后如果是奇环就打个标记,然后把奇环数++,删除的时候,把标记删 ...
 - 2018.09.30 bzoj4025: 二分图(线段树分治+并查集)
		
传送门 线段树分治好题. 这道题实际上有很多不同的做法: cdq分治. lct. - 而我学习了dzyo的线段树分治+并查集写法. 所谓线段树分治就是先把操作分成lognlognlogn个连续不相交的 ...
 - BZOJ4025: 二分图【线段树分治】【带撤销的并查集】
		
Description 神犇有一个n个节点的图.因为神犇是神犇,所以在T时间内一些边会出现后消失.神犇要求出每一时间段内这个图是否是二分图.这么简单的问题神犇当然会做了,于是他想考考你. Input ...
 
随机推荐
- python网络编程(十)
			
select版-TCP服务器 1. select 原理 在多路复用的模型中,比较常用的有select模型和epoll模型.这两个都是系统接口,由操作系统提供.当然,Python的select模块进行了 ...
 - 编程菜鸟的日记-初学尝试编程-C++ Primer Plus 第5章编程练习2
			
#include <iostream>using namespace std;const int MAXSIZE=100;int main(){ int a[MAXSIZE]; int s ...
 - Redis、Memcache、MongoDb的优缺点
			
Redis.Memcache.MongoDb的优缺点 Redis优点 支持多种数据结构,如 string(字符串). list(双向链表).dict(hash表).set(集合).zset(排序set ...
 - 初识hibernate——环境搭建
			
一 配置过程 1. 创建一个项目 2. 导包 required里的包 optional里的c3p0连接池的三个包 数据库驱动包 Junit 3.创建Hibernate的配置文件(hiberna ...
 - Selenium上传文件方法总结
			
Web上本地上传图片,弹出的框Selenium是无法识别的,也就是说,selenium本身没有直接的方法去实现上传本地文件,这里总结了两种上传文件的方式. 一.利用Robot类处理文件上传. 其大致流 ...
 - 关于#!/bin/bash和#!/bin/sh
			
关于#!/bin/bash和#!/bin/sh #!/bin/bash是指此脚本使用/bin/bash来解释执行. 其中,#!是一个特殊的表示符,其后,跟着解释此脚本的shell路径. bash只 ...
 - 前端工程化系列[02]-Grunt构建工具的基本使用
			
本文主要介绍前端开发中常用的构建工具Grunt,具体包括Grunt的基本情况.安装.使用和常见插件的安装.配置和使用等内容. 1.1 Grunt简单介绍 Grunt是一套前端自动化构建工具.对于需要反 ...
 - wireshark解析自定义的protobuf协议
			
先看最终效果 wireshark是开源的,而且在Windows下安装时用的是64位,所以相应的库文件需要使用64位. 一个Lua插件的Dissector结构大致如下: do -- 协议名称为 m_Me ...
 - 表型数据(Phenotype Data)基本概念
			
表型(英语:Phenotype),又称表现型,对于一个生物而言,表示它某一特定的物理外观或成分.一个人是否有耳珠.植物的高度.人的血型.蛾的颜色等等,都是表型的例子. 表型主要受生物的基因型和环境影响 ...
 - 条件式变分自编码机(Conditional Variational Autoencoders)
			
Conditional Variational Autoencoders 条件式变换自编码机 摘要: Conditional Variational Autoencoders --- 条件式变换自编码 ...