题目大意

  给你一张\(n\)个点\(m\)条边的无向图,问删去每个点后,原图是不是二分图。

  \(n,m\leq 100000\)

题解

  一个图是二分图\(\Longleftrightarrow\)该图不存在奇环

  可以用并查集,维护每个点到根的距离

  如果删除\(x\)点,就要把所有不与\(x\)连接的边加入并查集

  考虑分治,对于区间\([l,r]\),我们先把与\([l,mid]\)链接且不与\([mid+1,r]\)链接的边加入并查集,然后递归处理\([mid+1,r]\)。另一边的情况类似。

  因为有撤销操作,所以要用按秩合并的并查集

  时间复杂度:\(O(m\log^2 n)\)

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<ctime>
#include<utility>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
struct list
{
int v[200010];
int t[200010];
int h[100010];
int n;
void clear()
{
memset(h,0,sizeof h);
n=0;
}
void add(int x,int y)
{
n++;
v[n]=y;
t[n]=h[x];
h[x]=n;
}
};
list li;
int f[100010];
int s[100010];
int d[100010];
int find(int x)
{
return f[x]==x?x:find(f[x]);
}
int getdist(int x)
{
return f[x]==x?0:getdist(f[x])^d[x];
}
int e1[100010];
int e2[100010];
int top;
int ans[100010];
int merge(int x,int y)
{
int dist=getdist(x)^getdist(y)^1;
if((x=find(x))==(y=find(y)))
return dist;
top++;
if(s[x]<=s[y])
{
e1[++top]=x;
e2[top]=y;
d[x]=dist;
s[y]+=s[x];
f[x]=y;
}
else
{
e1[++top]=y;
e2[top]=x;
d[y]=dist;
s[x]+=s[y];
f[y]=x;
}
return 0;
}
void solve(int l,int r)
{
if(l==r)
{
ans[l]=1;
return;
}
int mid=(l+r)>>1;
int now=top;
int i,j;
int b=1;
for(i=l;i<=mid&&b;i++)
for(j=li.h[i];j&&b;j=li.t[j])
if(li.v[j]<=mid||li.v[j]>r)
b^=merge(i,li.v[j]);
if(b)
solve(mid+1,r);
else
for(i=mid+1;i<=r;i++)
ans[i]=0;
while(top>now)
{
f[e1[top]]=e1[top];
s[e2[top]]-=s[e1[top]];
top--;
}
now=top;
b=1;
for(i=mid+1;i<=r&&b;i++)
for(j=li.h[i];j&&b;j=li.t[j])
if(li.v[j]<l||li.v[j]>mid)
b^=merge(i,li.v[j]);
if(b)
solve(l,mid);
else
for(i=l;i<=mid;i++)
ans[i]=0;
while(top>now)
{
f[e1[top]]=e1[top];
s[e2[top]]-=s[e1[top]];
top--;
}
}
void solve()
{
top=0;
int n,m;
scanf("%d%d",&n,&m);
int i;
int x,y;
li.clear();
for(i=1;i<=m;i++)
{
scanf("%d%d",&x,&y);
li.add(x,y);
li.add(y,x);
}
for(i=1;i<=n;i++)
{
f[i]=i;
s[i]=1;
}
solve(1,n);
for(i=1;i<=n;i++)
putchar(ans[i]+'0');
putchar('\n');
}
int main()
{
// freopen("c.in","r",stdin);
// freopen("c.out","w",stdout);
int t;
scanf("%d",&t);
while(t--)
solve();
return 0;
}

【XSY2469】graph 分治 并查集的更多相关文章

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

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

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

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

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

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

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

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

  5. [HDU5354]Bipartite Graph(CDQ分治+并查集)

    经典动态二分图问题. 考虑solve(l,r)分治成l,mid和mid+1,r.先将区间[mid+1,r]中的点全部加入图中,若此时存在奇环则ans[l..mid]全部为0,否则递归到左边. 递归完左 ...

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

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

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

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

  8. 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 ...

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

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

随机推荐

  1. H5 58-网页的布局方式

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  2. Python学习第十篇——函数初步

    def make_album(name,album_name,song_nums = 1): dict_album = {name:[album_name]} if int(song_nums) &g ...

  3. html总结:float实现span和input输入框同行

    例: <input type="text" name="ytdwname" value="<%=user.getYtdwname() %& ...

  4. 【kindle笔记】之 《明朝那些事儿》-2018-7-1

    [kindle笔记]读书记录-总 最近在读这本书.之前在微信读书里断断续续读过,读到深处还想蹦起来做笔记那种.后来种种原因断了,再没续上. 现在又开始啦.最近还在重八兄造反阶段,还很早呢,有时候晚上玩 ...

  5. 项目管理、软件、禅道 VS JIRA

    项目管理软件之争,禅道和JIRA大对比 - 简书https://www.jianshu.com/p/2533c0b7e456 [原创]项目管理软件之争,禅道和JIRA大对比 - zhengqiaoyi ...

  6. React Native之微信分享(iOS Android)

    React Native之微信分享(iOS Android) 在使用React Native开发项目的时候,基本都会使用到微信好友或者微信朋友圈分享功能吧,那么今天我就带大家实现以下RN微信好友以及朋 ...

  7. leetcode资料整理

    注:借鉴了 http://m.blog.csdn.net/blog/lsg32/18712353 在Github上提供leetcode有: 1.https://github.com/soulmachi ...

  8. git修改用户名、邮箱

    在windows使用git命令方法如下(以win7为例):1.msysgit 是 Windows 版的 Git可以百度搜索Git下载.2.安装完成后,开始菜单里找到“Git”->“Git Bas ...

  9. php分割中文字符串为数组的简单例子

    近日在做东西时,遇到要把中文字符进行逐字分割,试了很多方法,都不行,后来发现了一个超简单的方法: 分割字符串很简单,主要是用到函数preg_match_all.当处理含有中文的字符串时,可以用如下的方 ...

  10. select、poll、epoll之间的区别(搜狗面试)

    (1)select==>时间复杂度O(n) 它仅仅知道了,有I/O事件发生了,却并不知道是哪那几个流(可能有一个,多个,甚至全部),我们只能无差别轮询所有流,找出能读出数据,或者写入数据的流,对 ...