题目链接:hdu_5354_Bipartite Graph

题意:

给你一个由无向边连接的图,问对于每一个点来说,如果删除这个点,剩下的点能不能构成一个二分图。

题解:

如果每次排除一个点然后去DFS判是否为二分图,那肯定会超时。

我们可以知道,删除其中一个点,对其他好多的边都不会有影响,所以我们可以将其他点的边先加进去,然后来判断一个区间的点是否可行。

这就和cdq分治的思想差不多。我们令cdq(l,r)表示解决l到r区间的答案。然后通过并查集来判断已经加入的点是否为二分图。

并查集在判二分图的时候不能路径压缩,因为我们在cdq过程中会还原并查集的结构。

这里要注意,如果在更新[l,mid]时候,[mid+1,r]只要不能构成二分图,那么[l,mid]的答案就全部都是0,然后就是在并查集合并的时候要以节点多的树为跟,这样才不会T。

 #include<bits/stdc++.h>
#define F(i,a,b) for(int i=a;i<=b;i++)
using namespace std; const int N=1e5+;
int t,n,m,ed,g[N],v[N*],nxt[N*],rk[N],col[N],top,fa[N];
char ans[N];
struct node
{
int u,v,colu,colv,fau,fav,rku,rkv;
node(){}
node(int _u,int _v,int _colu,int _colv,int _fau,int _fav,int _rku,int _rkv):
u(_u),v(_v),colu(_colu),colv(_colv),fau(_fau),fav(_fav),rku(_rku),rkv(_rkv){}
}S[N],tmp; void init(){ed=top=,ans[n+]=;F(i,,n)g[i]=,rk[i]=col[i]=,fa[i]=i;}
void adg(int x,int y){v[++ed]=y,nxt[ed]=g[x],g[x]=ed;} inline int find_fa(int x){return fa[x]==x?x:find_fa(fa[x]);}
inline int find_col(int x)
{
if(fa[x]==x)return col[x];
return col[x]?find_col(fa[x]):!find_col(fa[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);
if(fa_u==fa_v)
{//如果同根并且同色,又有这条边,该图肯定不是二分图
if(col_u==col_v)return ;
return ;
}
int rt,son;
if(rk[fa_u]<rk[fa_v])rt=fa_v,son=fa_u;else rt=fa_u,son=fa_v;//以大树为根
S[++top]=node(rt,son,col[rt],col[son],fa[rt],fa[son],rk[rt],rk[son]);
if(col_u==col_v)col[son]^=;//如果要合并的两个点的颜色相同,那么将要作为儿子的点改变颜色
fa[son]=rt,rk[rt]+=rk[son];
return ;
} void back(int pre)//还原并查集
{
while(top>pre)
{
tmp=S[top--];
int u=tmp.u,v=tmp.v;
col[u]=tmp.colu,col[v]=tmp.colv;
fa[u]=tmp.fau,fa[v]=tmp.fav;
rk[u]=tmp.rku,rk[v]=tmp.rkv;
}
} int unite(int l,int r,int a,int b)
{
F(j,l,r)for(int i=g[j];i;i=nxt[i])
{
if(a<=v[i]&&v[i]<=b)continue;//只合并[l,r]区间的点
if(!merge(j,v[i]))return ;
}
return ;
} void cdq(int l=,int r=n,int flag=)
{
if(l==r){ans[l]=flag+'';return;}
int mid=l+r>>,pre=top,now=flag&&unite(mid+,r,l,mid);
cdq(l,mid,now),back(pre);
now=flag&&unite(l,mid,mid+,r);
cdq(mid+,r,now),back(pre);
} int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
init();
F(i,,m)
{
int x,y;
scanf("%d%d",&x,&y);
adg(x,y),adg(y,x);
}
cdq(),printf("%s\n",ans+);
}
return ;
}

hdu_5354_Bipartite Graph(cdq分治+并查集判二分图)的更多相关文章

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

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

  2. 2015多校第6场 HDU 5354 Bipartite Graph CDQ,并查集

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5354 题意:求删去每个点后图是否存在奇环(n,m<=1e5) 解法:很经典的套路,和这题一样:h ...

  3. 【openjudge】C15C Rabbit's Festival CDQ分治+并查集

    题目链接:http://poj.openjudge.cn/practice/C15C/ 题意:n 点 m 边 k 天.每条边在某一天会消失(仅仅那一天消失).问每一天有多少对点可以相互到达. 解法:开 ...

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

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

  5. 2018.10.01 bzoj3237: [Ahoi2013]连通图(cdq分治+并查集)

    传送门 cdq分治好题. 对于一条边,如果加上它刚好连通的话,那么删掉它会有两个大集合A,B.于是我们先将B中禁用的边连上,把A中禁用的边禁用,再递归处理A:然后把A中禁用的边连上,把B中禁用的边禁用 ...

  6. 【CF603E】Pastoral Oddities cdq分治+并查集

    [CF603E]Pastoral Oddities 题意:有n个点,依次加入m条边权为$l_i$的无向边,每次加入后询问:当前图是否存在一个生成子图,满足所有点的度数都是奇数.如果有,输出这个生成子图 ...

  7. BZOJ1997 HNOI2010 平面图判定 planar (并查集判二分图)

    题意 判断一个存在哈密顿回路的图是否是平面图. n≤200,m≤10000n\le200,m\le10000n≤200,m≤10000 题解 如果一定存在一个环,那么连的边要么在环里面要么在外面.那么 ...

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

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

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

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

随机推荐

  1. 数据结构之Binary Search Tree (Java)

    二叉查找树简介 二叉查找树(Binary Search Tree), 也成二叉搜索树.有序二叉树(ordered binary tree).排序二叉树(sorted binary tree), 是指一 ...

  2. 【LeetCode】22. Generate Parentheses (I thought I know Python...)

    I thought I know Python... Actually , I know nothing... 这个题真想让人背下来啊,每一句都很帅!!! Given n pairs of paren ...

  3. org.apache.log4j.Logger 详解

    org.apache.log4j.Logger 详解 1. 概述 1.1. 背景    在应用程序中添加日志记录总的来说基于三个目的 :监视代码中变量的变化情况,周期性的记录到文件中供其他应用进行统计 ...

  4. udp接收

    char receive_buffer[500] = {0}; std::vector<std::string> mysplit(std::string str,std::string p ...

  5. MATLAB初体验

    好激动 要入MATLAB的大坑了 恩 很遗憾第一个程序并不是hello world 好 插入代码里并没有MATLAB这个选项 这是一种歧视 x=[:pi/:*pi]; y=sin(x); plot(x ...

  6. mysql版本,根据经纬度定位排序sql

    SELECT id,lng,lat,ROUND(6378.138*2*ASIN(SQRT(POW(SIN((lat1*PI()/180-lat*PI()/180)/2),2)+COS(lat1*PI( ...

  7. Android中设定EditText的输入长度

    方法一:可以在layout xml中加上属性android:maxLength 比如: <EditText         android:id="@+id/editTextShow& ...

  8. Scala Singleton对象

    Scala Object: scala没有静态的修饰符,例如Java中的static.但是Scala提供了Object类型,object下的成员都是静态的,比较像Java的静态类.不同在于Scala的 ...

  9. 第一百一十六节,JavaScript,DOM操作样式

    JavaScript,DOM操作样式 一.操作样式 CSS作为(X)HTML的辅助,可以增强页面的显示效果.但不是每个浏览器都能支持最新的CSS能力.CSS的能力和DOM级别密切相关,所以我们有必要检 ...

  10. 面试题-Java基础-垃圾回收

    1.Java中垃圾回收有什么目的?什么时候进行垃圾回收? 垃圾回收的目的是识别并且丢弃应用不再使用的对象来释放和重用资源. 2.System.gc()和Runtime.gc()会做什么事情? 这两个方 ...