题目大意

  给你一张\(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. Linux查看端口

    1.lsof -i:端口号 用于查看某一端口的占用情况,比如查看8000端口使用情况,lsof -i:8000   2.netstat -tunlp |grep 端口号 用于查看指定的端口号的进程情况 ...

  2. Linux安装Apache常见报错(一)

    启动Apache提示报错:Could not reliably determine the server's fully qualified domain name, using localhost, ...

  3. Vue+min-width实现最大两栏布局

    <style> .fitting-Modal-details{ overflow: hidden; } .detailsContent{ float: left; min-width: 5 ...

  4. 2 Modals of necessity

    1 情况动词must 和词组have to, need to ,have got to 都表示必须做某事或者要求做某事. need to  have to  must have got to When ...

  5. Day 5-8 自定义元类控制类的实例化行为

    __call__方法: 对象后面加括号,触发执行. 注:构造方法的执行是由创建对象触发的,即:对象 = 类名() :而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类( ...

  6. API知识点总结

    一.开发api接口开放给其他人调用的api接口(短信接口,支付宝api) 二.api安全弱点数据窃取(解决加密),数据篡改(解决MD5),数据泄露(爬虫技术)(解决令牌)1.加密(HTTPS传输-收费 ...

  7. Django Rest framework 框架之认证使用和源码执行流程

    用这个框架需要先安装: pip3 install djangorestframework 如果写了一个CBV的东西,继承了View. # 继承Django里面View class APIView(Vi ...

  8. Leetcode SingleNumber I & II & III 136/137/260

    SingleNumber I: 题目链接:https://leetcode-cn.com/problems/single-number/ 题意: 给定一个非空整数数组,除了某个元素只出现一次以外,其余 ...

  9. RDD特性

  10. git简介及安装(win10)

    一句话介绍git Git是Linus Torvalds编写,目前是世界上最先进的分布式版本控制系统. git能干什么? 代码备份.还原,版本管理,分支管理,解决冲突,协同开发... 安装git > ...