题意

   给定一张 \(n\) 个点 \(m\) 条边的无向图,问删去每个点后,原图是不是二分图。输出一个长度为 \(n\) 的 \(\text{01}\) 串表示答案。

   多组数据。

   \(T\le 5,\space 1\le n,m\le 10^5,\space 1\le u,v\le n,\space u≠v\)

题解

   不难发现,一个没有奇环(奇数条边的环)的图就是二分图。

   考虑分治,若一个分治区间外的点已经连出了奇环,那删掉这个区间的每个点的答案都是 \(0\)。若分治到区间长度为 \(1\) 时,这个区间外的点还没连出奇环,那删掉这个点的答案就是 \(1\)。

   可以用并查集检测奇环,但由于分治回溯时需要撤销连边,不能路径压缩,所以用按秩合并的并查集。注意按照大小合并,按深度合并会 TLE。

   考虑如何判断新加的一条边的两端点是否颜色相同(即是否连出奇环)。

   初始时设每个点的颜色为 \(0\)(也可以为 \(1\),这里为了让接下来的操作方便理解,就设成 \(0\))。不难发现当两个并查集合并时,连接这两个并查集的边的两端点的颜色可能相同,这时我们最简单的解决方式是 把小的并查集的所有点的颜色都反转。

   但是我们显然不能暴力扫一遍子树,这样复杂度是错的。

   回想一下,我们按秩合并的并查集的深度是不是 \(\log\) 的?

   那我们求一个点的颜色时,只需要从这个点往根扫一遍就行了吧?

   所以我们只需要修改小的并查集的根节点颜色。具体地,并查集的每个点维护一个 \(\text{01}\) 标记,\(\text{0}\) 表示以该点为根的子树不翻转颜色,\(\text{1}\) 表示以该点为根的子树翻转颜色。一个点的颜色就是 该点 到 其所在的并查集的根节点 上所有点颜色的异或和。

   一个细节:边一定都是从小分治区间的点 往大分治区间的点连。

#include<bits/stdc++.h>
#define N 100010
using namespace std;
inline int read(){
int x=0; bool f=1; char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=0;
for(; isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+c-'0';
if(f) return x;
return 0-x;
} int n,m,col[N],fa[N],siz[N];
char ans[N]; struct edge{int v,nxt;}e[N<<1];
int hd[N],cnt;
inline void add(int u, int v){e[++cnt]=(edge){v,hd[u]}, hd[u]=cnt;} struct DSU{int u,v,col_u,col_v,siz_u,siz_v;}stk[N],tmp;
int top; inline void init(){
top=cnt=0;
ans[n+1]=0;
for(int i=1; i<=n; ++i) hd[i]=col[i]=0, siz[i]=1, fa[i]=i;
}
int find_fa(int x){
return fa[x]==x ? x : find_fa(fa[x]);
}
int find_col(int x){
if(fa[x]==x) return col[x]; //显然根的col为0
return find_col(fa[x])^col[x];
}
int merge(int u, int v){
int fa_u=find_fa(u), fa_v=find_fa(v);
int col_u=find_col(u), col_v=find_col(v);
//cout<<u<<' '<<v<<' '<<fa_u<<' '<<fa_v<<' '<<col_u<<' '<<col_v<<endl;
if(fa_u==fa_v){
if(col_u==col_v) return 0;
return 1;
}
int rt,son;
if(siz[fa_u]<siz[fa_v]) rt=fa_v, son=fa_u;
else rt=fa_u, son=fa_v;
//cout<<rt<<endl;
stk[++top] = (DSU){rt,son,col[rt],col[son],siz[rt],siz[son]};
if(col_u==col_v) col[son]^=1;
fa[son]=rt, siz[rt]+=siz[son];
return 1;
}
void undo(int pre){
//printf("undo\n");
while(top>pre){
tmp=stk[top--];
int u=tmp.u, v=tmp.v;
col[u]=tmp.col_u, col[v]=tmp.col_v;
fa[u]=u, fa[v]=v;
siz[u]=tmp.siz_u, siz[v]=tmp.siz_v;
}
}
int unite(int l, int r, int a, int b){
//printf("unite\n");
for(int j=l; j<=r; ++j)
for(int i=hd[j]; i; i=e[i].nxt){
if(a<=e[i].v && e[i].v<=b) continue;
if(!merge(j,e[i].v)) return 0;
}
return 1;
}
void cdq(int l, int r, bool flag){
//printf("cdq:%d %d %d\n",l,r,flag);
if(l==r){ans[l]=flag+'0'; return;}
int mid=l+r>>1;
if(!flag){
cdq(l,mid,0), cdq(mid+1,r,0);
return;
}
int pre=top; bool now=unite(mid+1,r,l,mid);
cdq(l,mid,now), undo(pre);
now = unite(l,mid,mid+1,r);
cdq(mid+1,r,now), undo(pre);
}
int main(){
int T=read();
while(T--){
n=read(), m=read();
init();
int u,v;
for(int i=1; i<=m; ++i) u=read(), v=read(), add(u,v), add(v,u);
cdq(1,n,1);
printf("%s\n",ans+1);
}
return 0;
}

【bzoj 4025 改编版】graph的更多相关文章

  1. bzoj 4025 二分图 分治+并查集/LCT

    bzoj 4025 二分图 [题目大意] 有n个点m条边,边会在start时刻出现在end时刻消失,求对于每一段时间,该图是不是一个二分图. 判断二分图的一个简单的方法:是否存在奇环 若存在奇环,就不 ...

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

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

  3. BZOJ 4025: 二分图 [线段树CDQ分治 并查集]

    4025: 二分图 题意:加入边,删除边,查询当前图是否为二分图 本来想练lct,然后发现了线段树分治的做法,感觉好厉害. lct做法的核心就是维护删除时间的最大生成树 首先口胡一个分块做法,和hno ...

  4. BZOJ百题版切计划(不咕)

    传送门 BZOJ 前言 听说最近要省选,那么我就写一下吧.QwQ! 1000 过于简单,不写了. 1001 不会对偶图,直接优化最小割 题解 1002 高精度套公式计算 题解 (Code by hey ...

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

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

  6. 【BZOJ 4025】 (CDQ?还是整体二分?+并查集及它的恢复操作)

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

  7. BZOJ 4025 二分图(时间树+并查集)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=4025 [题目大意] 给出一张图,有些边只存在一段时间,问在一个每个时间段, 这张图是否 ...

  8. bzoj 4025: 二分图

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

  9. https://github.com/tensorflow/models/blob/master/research/slim/datasets/preprocess_imagenet_validation_data.py 改编版

    #!/usr/bin/env python # Copyright 2016 Google Inc. All Rights Reserved. # # Licensed under the Apach ...

随机推荐

  1. OAUTH协议介绍

    OAUTH协议为用户资源的授权提供了一个安全的.开放而又简易的标准.与以往的授权方式不同之处是OAUTH的授权不会使第三方触及到用户的帐号信息(如用户名与密码),即第三方无需使用用户的用户名与密码就可 ...

  2. EL表达式与JSTL标签库(一)

    1.JSTL概述 JSTL标签库由标签库和EL表达式两个部分组成.JSTL标准标签库(Java Server Page Standard Tag Library),用来解决创建的页面的操作问题,包括输 ...

  3. jQuery选择:子代元素与后代元素的区别

    (1)后代元素:html代码如下,那么在jquery选择时,$(".test img"),中间为空格,则是选取后代元素,img对于ul来说是孙子辈元素,中间隔了li元素,所以后代元 ...

  4. WinRar制作安装包

    这次研究了下WinRar制作程序安装包,我使用的是5.21版本. 选中要打包的文件,先压缩为RAR文件,然后双击打开文件 输入目录时可以选择前两项,输入绝对路径时,则为第三项. 配置解压前运行的解压后 ...

  5. 网络实验 03-交换机划分VLAN配置

    交换机划分VLAN配置 一.实验目标 理解虚拟 LAN(VLAN)基本原理 掌握一般交换机按端口划分 VLAN的配置方法 掌握Tag VLAN配置方法 二.实验背景 某一公司内财务部.销售部的PC通过 ...

  6. WDM-波分复用

    波分复用WDM(Wavelength Division Multiplexing)是将两种或多种不同波长的光载波信号(携带各种信息)在发送端经复用器(亦称合波器,Multiplexer)汇合在一起,并 ...

  7. js动态修改浏览器title

    script标签依据浏览框的失焦获焦进行函数操作(操作简单放到HTML文件下的head标签下就可以) <script> window.onfocus = function () { doc ...

  8. 【AMAD】betamax -- 一个ruby-VCR的模仿品,只支持requests

    简介 动机 作用 用法 个人评分 简介 betamax1会记录你的HTTP操作,可以让你在测试的时候不必重复进行真实的请求. 动机 如果你的代码需要和外部资源一起运作,那么测试这段代码的方法就叫做集成 ...

  9. finereport 通过条件弹出 alert进行提示

    function convertDateFromString(dateString) { if (dateString) { var date = new Date(dateString.replac ...

  10. Mac下搭建Apache+PHP+MySql运行环境

    https://www.cnblogs.com/xiaovw/p/8854896.html 前言 我们在Mac上搭建Apache+PHP+MySql环境是非常方便的,因为Mac预装的有Apache和P ...