[bzoj4025]二分图_LCT
二分图 bzoj-4025
题目大意:给定一个n个节点的图,m条边,每条边有一个产生时间和一个删除时间,询问所有时间点是否是连通图。
注释:$1\le n\le 10^5$,$1\le m\le 2\cdot 10^5$
想法:好难...
又是一道结论题。开始不知道结论,在那里LCT不知道怎么判二分图... ...
其实就是判每一个时刻有没有奇环... ...硬核题...
紧接着,我们考虑如何维护。
我们先随便弄出一棵生成树,然后我们想维护这样的集合S。S中的任意一条边都会和生成树构成奇环。
有一种情况我们没有办法处理,就是把集合的边加上,然后... ...树边没了,我们还要把集合中的边换成树边,非常麻烦,码量堪忧。
所以,我们要维护最大删除时间生成树,就不会出现以上情况。
最后,附上丑陋的代码... ...
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define ls ch[p][0]
#define rs ch[p][1]
#define get(x) (ch[f[x]][1]==x)
#define N 100010
using namespace std;
struct Node
{
int x,y,t1,t2;
}a[N<<1];
int n,f[N<<2],ch[N<<2][2],size[N<<2],w[N<<2],mp[N<<2],rev[N<<2],num[N];
int sum,now;
inline char nc()
{
static char buf[100000],*p1,*p2;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline int read()
{
int ret=0; char ch=nc();
while(!isdigit(ch)) ch=nc();
while(isdigit(ch)) ret=(ret<<3)+(ret<<1)+ch-48,ch=nc();
return ret;
}
inline bool cmp(const Node &a,const Node &b)
{
return a.t1<b.t1;
}
inline void pushup(int p)
{
size[p]=size[ls]+size[rs]+1;
mp[p]=p;
if(w[mp[ls]]<w[mp[p]]) mp[p]=mp[ls];
if(w[mp[rs]]<w[mp[p]]) mp[p]=mp[rs];
}
inline void pushdown(int p)
{
if(!rev[p]) return;
swap(ch[ls][0],ch[ls][1]); swap(ch[rs][0],ch[rs][1]);
rev[ls]^=1; rev[rs]^=1; rev[p]=0;
}
inline bool isroot(int p)
{
return ch[f[p]][0]!=p&&ch[f[p]][1]!=p;
}
void update(int p)
{
if(!isroot(p)) update(f[p]);
pushdown(p);
}
void rotate(int x)
{
int y=f[x],z=f[y],k=get(x);
if(!isroot(y)) ch[z][ch[z][1]==y]=x;
ch[y][k]=ch[x][!k]; f[ch[y][k]]=y;
ch[x][!k]=y; f[y]=x; f[x]=z;
pushup(y); pushup(x);
}
void splay(int x)
{
update(x);
for(int t;t=f[x],!isroot(x);rotate(x))
{
if(!isroot(t)) rotate(get(x)==get(t)?t:x);
}
}
void access(int p)
{
int t=0;
while(p) splay(p),rs=t,pushup(p),t=p,p=f[p];
}
int find(int p)
{
access(p),splay(p);
while(ls) pushdown(p),p=ls;
return p;
}
inline void makeroot(int p)
{
access(p),splay(p);
swap(ls,rs),rev[p]^=1;
}
inline void link(int x,int y)
{
makeroot(x),f[x]=y;
}
inline void cut(int x,int p)
{
makeroot(x),access(p),splay(p);
f[x]=ls=0;pushup(p);
}
inline void split(int x,int y)
{
makeroot(x),access(y),splay(y);
}
void add(int p)
{
int tx=a[p].x,ty=a[p].y,tmp,flag=0;
if(tx==ty&&a[p].t2>now) num[a[p].t2]++,sum++;
else
{
if(find(tx)!=find(ty)) link(p+n,tx),link(ty,p+n);
else
{
split(tx,ty);
if(!((size[ty]>>1)&1)) flag=1;
if(w[mp[ty]]>=a[p].t2) tmp=p;
else tmp=mp[ty]-n,cut(tmp+n,a[tmp].x),cut(tmp+n,a[tmp].y),link(p+n,tx),link(p+n,ty);
if(flag&&a[tmp].t2>now) num[a[tmp].t2]++,sum++;
}
}
}
int main()
{
int m,t,p=1;
n=read(),m=read(),t=read();
for(int i=1;i<=m;i++) a[i].x=read(),a[i].y=read(),a[i].t1=read(),a[i].t2=read();
sort(a+1,a+m+1,cmp);
for(int i=1;i<=n+m;i++) size[i]=1,mp[i]=i;
for(int i=0;i<=n;i++) w[i]=1<<30;
for(int i=1;i<=m;i++) w[i+n]=a[i].t2;
for(int i=0;i<t;i++)
{
now=i;
while(p<=m&&a[p].t1<=i) add(p),p++;
sum-=num[i];
if(sum) puts("No");
else puts("Yes");
}
return 0;
}
小结:LCT就是强。
[bzoj4025]二分图_LCT的更多相关文章
- 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还很不熟--仅仅停留在极其简单的模板水平). 由于是带权并查集,并且不能路径压缩,所以对权值(到父亲距离的奇偶性)的维护要注意一下. 有一个小 ...
- bzoj4025二分图(线段树分治 并查集)
/* 思维难度几乎没有, 就是线段树分治check二分图 判断是否为二分图可以通过维护lct看看是否链接出奇环 然后发现不用lct, 并查集维护奇偶性即可 但是复杂度明明一样哈 */ #include ...
- bzoj4025 二分图 [分治,并查集]
传送门 思路 是二分图的充要条件:图没有奇环. 考虑按时间分治,用可撤销并查集维护点到根的距离. 仍然可以用一个小trick把两点连边变成根连边,可以看这里. 每次连边时若不连通则连上,否则判一下有没 ...
- bzoj4025: 二分图 lct
题意:带增删边的查询二分图 题解:因为二分图肯定带奇环,lct维护,每次要加入一条边之前判断会不会构成环,如果会就把最先会删除的边删掉,然后如果是奇环就打个标记,然后把奇环数++,删除的时候,把标记删 ...
- 2018.09.30 bzoj4025: 二分图(线段树分治+并查集)
传送门 线段树分治好题. 这道题实际上有很多不同的做法: cdq分治. lct. - 而我学习了dzyo的线段树分治+并查集写法. 所谓线段树分治就是先把操作分成lognlognlogn个连续不相交的 ...
- BZOJ4025: 二分图【线段树分治】【带撤销的并查集】
Description 神犇有一个n个节点的图.因为神犇是神犇,所以在T时间内一些边会出现后消失.神犇要求出每一时间段内这个图是否是二分图.这么简单的问题神犇当然会做了,于是他想考考你. Input ...
随机推荐
- 【转载】Java中Comparable和Comparator比较
[本文转自]http://www.cnblogs.com/skywang12345/p/3324788.html Comparable 简介 Comparable 是排序接口. 若一个类实现了Comp ...
- Java中static final 与 final 的区别(转载)
转自:http://advance0683.iteye.com/blog/1107732 Java中static final 与 final 的区别: 例子: Java代码 import java.u ...
- 9.12NOIP模拟题
NOIP 2017 全假模拟冲刺 hkd 题目名称 Spfa 走楼梯缩小版 滑稽 题目类型 传统 传统 传统 ...
- JavaScript中什么是包装对象?
存取字符串.数字或布尔值的属性时,创建的临时对象称为包装对象.包装对象只是偶尔用来区分字符串值和字符串对象.数字和数值对象以及布尔值和布尔对象.由于字符串.数字和布尔值的属性都是只读的,并且不能给它们 ...
- JavaScript--提问(prompt 消息对话框)
prompt弹出消息对话框,通常用于询问一些需要与用户交互的信息.弹出消息对话框(包含一个确定按钮.取消按钮与一个文本输入框). 语法: prompt(str1, str2); 参数说明: str1: ...
- 【Codeforces1117C_CF1117C】Magic Ship(构造)
题目: Codeforces1117C 考的时候很困,开局半小时后才过A,只做出来AB,排名3000+,掉了119--半夜体验极差. 翻译: 你是一个船长.最初你在点 \((x_1,y_1)\) (显 ...
- VS插件-Resharper
最近代码因为Resharper出现了点问题,同事问我这个插件有什么用,下面就列几个最近常用的功能.其他功能后续慢慢更新 1.什么是Resharper ReSharper是一个JetBrains公司出品 ...
- Java常用类库(三) : HashSet和LinkedList特点简析
今天内容: l 浅撩HashSet集合元素不可重复的原理 l 使用LinkedList模拟栈和队列 1.浅撩HashSet集合元素不可重复的原理 我们知道HashSet是添加不了相同的元素的,其原 ...
- Android RecyclerView使用 及 滑动时加载图片优化方案
1.控制线程数量 + 数据分页加载2.重写onScrollStateChanged方法 这个我们后面再谈,下面先来看看RecyclerView控件的使用及我们为什么选择使用它 RecyclerView ...
- Android项目实战_手机安全卫士splash界面
- 根据代码的类型组织包结构 1. 界面 com.hb.mobilesafe.activities 2. 服务 com.hb.mobilesafe.services 3. 业务逻辑 com.hb.mo ...