4025: 二分图

Time Limit: 20 Sec  Memory Limit: 512 MB
Submit: 2667  Solved: 989
[Submit][Status][Discuss]

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做法

其实就是求是否有奇环。先求出最小生成树,随后根据非树边两点间的距离得出是否有奇环。

lct维护以边消失时间为权值的最大生成树。这样可以保证所有已经进入集合的非树边都不会从集合中出来再次成为树边。
从小到达枚举时间进行加边和删边。
加边判奇环,更新最大生成树和集合.
删边如果是最大生成树里的边就在lct中删掉。否则仅在集合中删掉即可。

 #include<iostream>
#include<cstdlib>
#include<cmath>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define maxn 400001
using namespace std;
inline int read() {
char ch=getchar();int x=,f=;
for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-;
for(;isdigit(ch);ch=getchar()) x=x*+ch-'';
return x*f;
}
int n,m,T,ont[maxn*],jh[maxn*],tot,val[maxn*];
struct Edge {
int to[maxn*],nxt[maxn*],head[maxn*],cnt;
Edge(){memset(head,-,sizeof(head));cnt=;}
void add(int u,int v) {to[cnt]=v;nxt[cnt]=head[u];head[u]=cnt++;}
}e1,e2;
struct ASK {int u,v,w;}a[maxn*];
struct LCT {
struct Data {
int son[],sz,fa,rev,mn;
}t[maxn*];
bool isrt(int x) {return t[t[x].fa].son[]!=x&&t[t[x].fa].son[]!=x;}
void pushdown(int x) {
if(t[x].rev) {
swap(t[x].son[],t[x].son[]);
t[t[x].son[]].rev^=;t[t[x].son[]].rev^=;
t[x].rev=;
}
}
void pushup(int x) {
t[x].sz=t[t[x].son[]].sz+t[t[x].son[]].sz+(x>n);
t[x].mn=x;
if(val[t[t[x].son[]].mn]<val[t[x].mn]) t[x].mn=t[t[x].son[]].mn;
if(val[t[t[x].son[]].mn]<val[t[x].mn]) t[x].mn=t[t[x].son[]].mn;
}
void rotate(int x) {
int y=t[x].fa,z=t[y].fa;
bool l=(t[y].son[]==x),r=l^;
if(!isrt(y)) t[z].son[t[z].son[]==y]=x;
t[x].fa=z;t[y].fa=x;t[t[x].son[r]].fa=y;
t[y].son[l]=t[x].son[r];t[x].son[r]=y;
pushup(y);pushup(x);
}
void push(int x) {
if(!isrt(x)) push(t[x].fa);
pushdown(x);
}
void splay(int x) {
push(x);
while(!isrt(x)) {
int y=t[x].fa,z=t[y].fa;
if(!isrt(y)) {
if(t[y].son[]==x^t[z].son[]==y) rotate(x);
else rotate(y);
}
rotate(x);
}
}
void access(int x) {for(int pre=;x;pre=x,x=t[x].fa) {splay(x),t[x].son[]=pre;pushup(x);}}
void makert(int x) {access(x);splay(x);t[x].rev^=;}
void link(int x,int y) {makert(x);t[x].fa=y;}
void cut(int x,int y) {makert(x);access(y);splay(y);t[y].son[]=t[x].fa=;}
int find(int x) {access(x);splay(x);while(t[x].son[]) x=t[x].son[];return x;}
}lct;
void insert(int x,int u,int v,int w) {
if(u==v) {jh[x]=;tot++;return;}
if(lct.find(u)!=lct.find(v)) { ont[x]=;lct.link(u,n+x);lct.link(v,n+x);
}
else {
lct.makert(v);lct.access(u);lct.splay(u);int tmp=lct.t[u].mn-n;
if(a[tmp].w<a[x].w) {
if(!(lct.t[u].sz&)) {jh[tmp]=;tot++;}
lct.cut(a[tmp].u,tmp+n);lct.cut(a[tmp].v,tmp+n);
lct.link(u,n+x);lct.link(v,n+x);
ont[tmp]=;ont[x]=;
}
else {
if(!(lct.t[u].sz&)) {jh[x]=;tot++;}
}
}
}
void del(int x,int u,int v,int w) {
if(ont[x]) {lct.cut(u,x+n);lct.cut(v,x+n);}
else if(jh[x]) tot--;
}
int main() {
n=read(),m=read(),T=read();
memset(val,,sizeof(val));
for(int i=;i<=n;i++) lct.t[i].mn=i;
for(int i=;i<=m;i++) {
a[i].u=read(),a[i].v=read();int s=read(),t=read();
e1.add(s,i);e2.add(t,i);a[i].w=t;lct.t[n+i].sz=;lct.t[n+i].mn=n+i;val[n+i]=t;
}
for(int i=;i<T;i++) {
for(int j=e1.head[i];j>=;j=e1.nxt[j]) {
int to=e1.to[j];
insert(to,a[to].u,a[to].v,a[to].w);
}
for(int j=e2.head[i];j>=;j=e2.nxt[j]) {
int to=e2.to[j];
del(to,a[to].u,a[to].v,a[to].w);
}
if(!tot) printf("Yes\n");
else printf("No\n");
}
return ;
}
/*
45365
57727
*/

[BZOJ4025] 二分图 LCT/(线段树分治+并查集)的更多相关文章

  1. 2018.09.30 bzoj4025: 二分图(线段树分治+并查集)

    传送门 线段树分治好题. 这道题实际上有很多不同的做法: cdq分治. lct. - 而我学习了dzyo的线段树分治+并查集写法. 所谓线段树分治就是先把操作分成lognlognlogn个连续不相交的 ...

  2. BZOJ4025 二分图(线段树分治+并查集)

    之前学了一下线段树分治,这还是第一次写.思想其实挺好理解,即离线后把一个操作影响到的时间段拆成线段树上的区间,并标记永久化.之后一块处理,对于某个节点表示的时间段,影响到他的就是该节点一直到线段树根的 ...

  3. bzoj4025二分图(线段树分治 并查集)

    /* 思维难度几乎没有, 就是线段树分治check二分图 判断是否为二分图可以通过维护lct看看是否链接出奇环 然后发现不用lct, 并查集维护奇偶性即可 但是复杂度明明一样哈 */ #include ...

  4. BZOJ4025: 二分图【线段树分治】【带撤销的并查集】

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

  5. BZOJ3237:[AHOI2013]连通图(线段树分治,并查集)

    Description Input Output Sample Input 4 5 1 2 2 3 3 4 4 1 2 4 3 1 5 2 2 3 2 1 2 Sample Output Connec ...

  6. Bzoj1018/洛谷P4246 [SHOI2008]堵塞的交通(线段树分治+并查集)

    题面 Bzoj 洛谷 题解 考虑用并查集维护图的连通性,接着用线段树分治对每个修改进行分治. 具体来说,就是用一个时间轴表示图的状态,用线段树维护,对于一条边,我们判断如果他的存在时间正好在这个区间内 ...

  7. BZOJ 1018: [SHOI2008]堵塞的交通traffic(线段树分治+并查集)

    传送门 解题思路 可以离线,然后确定每个边的出现时间,算这个排序即可.然后就可以线段树分治了,连通性用并查集维护,因为要撤销,所以要按秩合并,时间复杂度\(O(nlog^2 n)\) 代码 #incl ...

  8. bzoj4025-二分图【线段树分治,并查集】

    正题 题目链接:https://darkbzoj.tk/problem/4025 题目大意 \(n\)个点\(m\)条边,每条边会在一个\(T\)以内的时间段内出现,对于任意一个\(T\)以内的时刻求 ...

  9. BZOJ3237 AHOI2013连通图(线段树分治+并查集)

    把查询看做是在一条时间轴上.那么每条边都有几段存在时间.于是线段树分治就好了. 然而在bzoj上t掉了,不知道是常数大了还是写挂了. 以及brk不知道是啥做数组名过不了编译. #include< ...

随机推荐

  1. How to speed up insertion performance in PostgreSQL

    Disable any triggers on the table Drop indexes before starting the import, re-create them afterwards ...

  2. tinyxml源码解析(上)

    转载于:http://www.cnblogs.com/marchtea/archive/2012/11/09/2762669.html 前言: 前段时间做功能可行性的时候简单的使用了tinyxml.在 ...

  3. springMVC新理解

    springmvc 中@Controller和@RestController的区别 1. Controller, RestController的共同点 都是用来表示spring某个类的是否可以接收HT ...

  4. Android数据存储与访问

    1.文件    1)保存到手要内存,文件保存到/data/data对应的应用程序包下面    如    FILE_PATH = "/data/data/com.diysoul.filedem ...

  5. 【题解】Matrix BZOJ 4128 矩阵求逆 离散对数 大步小步算法

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=4128 大水题一道 使用大步小步算法,把数字的运算换成矩阵的运算就好了 矩阵求逆?这么基础的线 ...

  6. Jupyter生成中文PDF的Notebook

    修改模板文件,将article.tplx文件中的\documentclass[11pt]{article}改为\documentclass[11pt]{ctexart} Linux下的文件路径一般在: ...

  7. android Handler post sendMessage

    Handler 为Android操作系统中的线程通信工具,包为android.os.Handler. 与Handler绑定的有两个队列,一个为消息队列,另一个为线程队列.Handler可以通过这两个队 ...

  8. Android 命名规范 (转)

    刚接触android的时候,命名都是按照拼音来,所以有的时候想看懂命名的那个控件什么是什么用的,就要读一遍甚至好几遍才知道,这样的话,在代码的审查和修改过程中就会浪费不少不必要的时间.如果就是我一个人 ...

  9. SPOJ 104 HIGH - Highways

    HIGH - Highways http://www.spoj.com/problems/HIGH/ In some countries building highways takes a lot o ...

  10. 51Nod 1381 硬币游戏 | 概率(数学期望)

    Input 第一行给出一个整数T,表示有T组数据(1<=T<=10000). 第2行到T+1,每行给出一个整数R.(0< R <= 10,000,000,000) Output ...