bzoj 4025 二分图

【题目大意】

  有n个点m条边,边会在start时刻出现在end时刻消失,求对于每一段时间,该图是不是一个二分图。

  判断二分图的一个简单的方法:是否存在奇环

  若存在奇环,就不是二分图。

  假设加入一条u->v的边,u,v已经联通,怎么知道是否是一个奇环呢?只需要知道u,v之间的距离就行了。距离为偶数则是一个奇环。

  路径?加边?删边?

  很容易就想到是LCT。

  维护u->v的距离。

  每次加入一条边,就判断是否先前已经联通,否,则家父,若是,就判断u,v之间的距离。

  假若已经构成一个奇环,那么,在这个环的任意一条边都未被删除前,都不是二分图。

  那就在维护一个minv,表示最小的end值。加入一条边构成了环,就删掉最小end值的那条边,加入新边。

  由于是最小值,删掉不会有影响。(最小的end值的那条边肯定是先消失的)

  要把边拆成点,为了记录min值,以及对应的边。

  细节,慢慢处理就好了。(被坑了好久……)

注意:有自环,需特判。

【附上代码】

#include<cstdio>
#include<algorithm> #define imax(a,b) ((a>b)?(a):(b))
#define imin(a,b) ((a<b)?(a):(b)) using namespace std; const int N=100010;
int n,m,T,cnt,len;
struct tree
{
tree *c[2],*f,*pp,*L,*R;
bool flip;
int minv,val,siz;
int d() { return (f->c[1]==this); }
void sc(tree *x,int d) { (c[d]=x)->f=this; }
} nil[N*3],*ro[N*3],*stack[N*3];
struct data { int u,v,start,end; } d[N<<1];
int ans[N]; tree *newtree()
{
nil[++cnt]=nil[0];
return nil+cnt;
} void down(tree *x)
{
if(x==nil) return;
if(x->flip)
{
x->flip=0;
swap(x->c[0],x->c[1]);
if(x->c[0]!=nil) x->c[0]->flip^=1;
if(x->c[1]!=nil) x->c[1]->flip^=1;
}
} void up(tree *x)
{
if(x==nil) return;
x->minv=x->val; x->siz=1;
if(x->c[0]!=nil) x->minv=imin(x->minv,x->c[0]->minv),x->siz+=x->c[0]->siz;
if(x->c[1]!=nil) x->minv=imin(x->minv,x->c[1]->minv),x->siz+=x->c[1]->siz;
} void rotate(tree *x)
{
int d=x->d();
tree *y=x->f;
y->sc(x->c[!d],d);
if(y->f==nil) x->f=nil; else y->f->sc(x,y->d());
x->sc(y,!d);
up(y); up(x);
x->pp=y->pp;
y->pp=nil;
} void splay(tree *x)
{
int hy=1;
stack[hy]=x;
for(;stack[hy]->f!=nil;hy++) stack[hy+1]=stack[hy]->f;
for(;hy;) down(stack[hy]),hy--;
for(tree *y;x->f!=nil;)
{
y=x->f;
if(y->f!=nil)
(x->d()^y->d())?rotate(x):rotate(y);
rotate(x);
}
} void access(tree *x)
{
tree *y=nil;
while(x!=nil)
{
splay(x);
if(x->c[1]!=nil)
{
x->c[1]->f=nil;
x->c[1]->pp=x;
}
x->c[1]=y;
if(y!=nil)
{
y->f=x;
y->pp=nil;
}
up(x);
y=x; x=x->pp;
}
} void evert(tree *x)
{
access(x);
splay(x);
x->flip^=1;
} void link(tree *x,tree *y)
{
evert(y);
y->pp=x;
} void cut(tree *x,tree *y)
{
evert(x);
access(y);
splay(y);
if(y->c[0]!=nil)
{
y->c[0]->f=nil;
y->c[0]=nil;
}
up(y);
} tree *findroot(tree *x)
{
access(x);
splay(x);
while(x->c[0]!=nil)
{
x=x->c[0];
down(x);
}
splay(x);
return x;
} tree *findmin(tree *x,tree *y)
{
evert(x);
access(y);
splay(x); down(x);
len=(x->siz+1)>>1;
int find=x->minv;
for(;;)
{
if(x->val==find) break;
if(x->c[0]!=nil && x->c[0]->minv==find) x=x->c[0];
else x=x->c[1];
down(x);
}
splay(x);
return x;
} bool cmp(data A,data B) { return (A.start<B.start); } int main()
{
scanf("%d%d%d",&n,&m,&T); cnt=0;
nil->val=nil->minv=1e9; nil->siz=0; nil->pp=nil;
nil->f=nil->c[0]=nil->c[1]=nil->L=nil->R=nil;
for(int i=1;i<=m;i++) scanf("%d%d%d%d",&d[i].u,&d[i].v,&d[i].start,&d[i].end);
sort(d+1,d+1+m,cmp);
for(int i=1;i<=n;i++) ro[i]=newtree();
for(int i=1;i<=m;i++)
{
ro[n+i]=newtree();
ro[n+i]->val=d[i].end; ro[n+i]->minv=d[i].end;
ro[n+i]->L=ro[d[i].u]; ro[n+i]->R=ro[d[i].v];
}
for(int i=1;i<=m;i++)
{
if(d[i].u==d[i].v)
{
ans[d[i].start]++; ans[d[i].end]--;
continue;
}
if(findroot(ro[d[i].u])!=findroot(ro[d[i].v]))
{
link(ro[d[i].u],ro[n+i]);
link(ro[n+i],ro[d[i].v]);
}
else
{
tree *getmin=findmin(ro[d[i].u],ro[d[i].v]);
if(d[i].start<getmin->val && (len&1))
{
ans[d[i].start]++;
ans[imin(getmin->val,d[i].end)]--; //重点啊,我就被这里坑了
}
if(d[i].end>getmin->val)
{
cut(getmin,getmin->L);
cut(getmin,getmin->R);
link(ro[d[i].u],ro[n+i]);
link(ro[n+i],ro[d[i].v]);
}
}
}
int yu=0;
for(int i=0;i<T;i++)
{
yu+=ans[i];
if(yu>0) printf("No\n"); else printf("Yes\n");
}
return 0;
}

【其他思路】

  分治+可回溯并查集(就是不带路径压缩的并查集)

  Solve(L,R,S)表示处理L到R这个时间段,有关联的边集为S。

  如果存在L->R的时间段的边,且加入后构成了奇环,那么L->R这段时间都不为二分图,直接退出。

  把边集划分为左右两边,即边与左区间的交集归左边,右边的交集归右边。(是start和end的交集)

  然后先处理左边,再处理右边就行了。

  具体的看这里,我没写cdq分治,这是我同学的

bzoj 4025 二分图 分治+并查集/LCT的更多相关文章

  1. BZOJ4025 二分图 分治 并查集 二分图 带权并查集按秩合并

    原文链接http://www.cnblogs.com/zhouzhendong/p/8683831.html 题目传送门 - BZOJ4025 题意 有$n$个点,有$m$条边.有$T$个时间段.其中 ...

  2. [BZOJ 4025]二分图(线段树分治+带边权并查集)

    [BZOJ 4025]二分图(线段树分治+带边权并查集) 题面 给出一个n个点m条边的图,每条边会在时间s到t出现,问每个时间的图是否为一个二分图 \(n,m,\max(t_i) \leq 10^5\ ...

  3. bzoj 4025 二分图——线段树分治+LCT

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4025 线段树分治,用 LCT 维护链的长度即可.不过很慢. 正常(更快)的方法应该是线段树分 ...

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

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

  5. hdu_5354_Bipartite Graph(cdq分治+并查集判二分图)

    题目链接:hdu_5354_Bipartite Graph 题意: 给你一个由无向边连接的图,问对于每一个点来说,如果删除这个点,剩下的点能不能构成一个二分图. 题解: 如果每次排除一个点然后去DFS ...

  6. BZOJ_4025_二分图_线段树按时间分治+并查集

    BZOJ_4025_二分图_线段树按时间分治+并查集 Description 神犇有一个n个节点的图.因为神犇是神犇,所以在T时间内一些边会出现后消失.神犇要求出每一时间段内这个图是否是二分图.这么简 ...

  7. bzoj 3669: [Noi2014]魔法森林(并查集+LCT)

    Description 为了得到书法大家的真传,小E同学下定决心去拜访住在魔法森林中的隐士.魔法森林可以被看成一个包含个N节点M条边的无向图,节点标号为1..N,边标号为1..M.初始时小E同学在号节 ...

  8. 【CF576E】Painting Edges 线段树按时间分治+并查集

    [CF576E]Painting Edges 题意:给你一张n个点,m条边的无向图,每条边是k种颜色中的一种,满足所有颜色相同的边内部形成一个二分图.有q个询问,每次询问给出a,b代表将编号为a的边染 ...

  9. HDU 3081 Marriage Match II (二分图,并查集)

    HDU 3081 Marriage Match II (二分图,并查集) Description Presumably, you all have known the question of stab ...

随机推荐

  1. Android 使用WebView浏览有声音或者视频的网页,关闭WebView之后,声音或者视频不停止的解决办法

    笔者最近使用Eclipse开发Android移动应用app,其实有一个功能是使用Android系统自带的WebView控件加载Web页面.开发很顺利,浏览也很正常.不过有个比较特殊的一点就是加载的We ...

  2. 1A课程笔记分享_StudyJams_2017

    1A课程 概述 课程1A主要讲解了Android UI的三种基本控件:TextView.ImageView以及Button.笔记的主体内容主要根据课程内容的讲解顺序来组织,此外我对一些个人比较感兴趣的 ...

  3. mybatis中映射文件和实体类的关联性

    mybatis的映射文件写法多种多样,不同的写法和用法,在实际开发过程中所消耗的开发时间.维护时间有很大差别,今天我就把我认为比较简单的一种映射文件写法记录下来,供大家修改建议,争取找到一个最优写法~ ...

  4. GridView动态计算高度

    // 动态加载GridView 高度 public static void setListViewHeightBasedOnChildren(MyGridView myGridView) { List ...

  5. Escaping Closures 两点:本质是生命周期标示符

    1.block需要(拷贝)保存: 2.block引用的环境变量需要处理. 相当于oc中的copy block. Escaping Closures A closure is said to escap ...

  6. CAD动态绘制带面积周长的圆(com接口)

    CAD绘制图像的过程中,画圆的情况是非常常见的,用户可以在控件视区点取任意一点做为圆心,再动态点取半径绘制圆. 主要用到函数说明: _DMxDrawX::DrawCircle 绘制一个圆.详细说明如下 ...

  7. 用python写一个百度翻译

    运行环境: python 3.6.0 今天处于练习的目的,就用 python 写了一个百度翻译,是如何做到的呢,其实呢就是拿到接口,通过这个接口去访问,不过中间确实是出现了点问题,不过都解决掉了 先晾 ...

  8. jquery操作元素之间相邻的元素的获取方式

    <!DOCTYPE html><html> <head> <style> .siblings * { display: block; border: 2 ...

  9. vue移动端地址三级联动组件(二)

    继续上一篇: 子组件css: <style scoped lang="less"> #city { width: 100%; height: 100%; positio ...

  10. enote笔记语言(3)

    what&why(why not)&how&when&where&which:紫色,象征着神秘而又潜蕴着强大的力量,故取紫色. key&key-memo ...