hdu_5354_Bipartite Graph(cdq分治+并查集判二分图)
题意:
给你一个由无向边连接的图,问对于每一个点来说,如果删除这个点,剩下的点能不能构成一个二分图。
题解:
如果每次排除一个点然后去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分治+并查集判二分图)的更多相关文章
- [HDU5354]Bipartite Graph(CDQ分治+并查集)
经典动态二分图问题. 考虑solve(l,r)分治成l,mid和mid+1,r.先将区间[mid+1,r]中的点全部加入图中,若此时存在奇环则ans[l..mid]全部为0,否则递归到左边. 递归完左 ...
- 2015多校第6场 HDU 5354 Bipartite Graph CDQ,并查集
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5354 题意:求删去每个点后图是否存在奇环(n,m<=1e5) 解法:很经典的套路,和这题一样:h ...
- 【openjudge】C15C Rabbit's Festival CDQ分治+并查集
题目链接:http://poj.openjudge.cn/practice/C15C/ 题意:n 点 m 边 k 天.每条边在某一天会消失(仅仅那一天消失).问每一天有多少对点可以相互到达. 解法:开 ...
- BZOJ 4025: 二分图 [线段树CDQ分治 并查集]
4025: 二分图 题意:加入边,删除边,查询当前图是否为二分图 本来想练lct,然后发现了线段树分治的做法,感觉好厉害. lct做法的核心就是维护删除时间的最大生成树 首先口胡一个分块做法,和hno ...
- 2018.10.01 bzoj3237: [Ahoi2013]连通图(cdq分治+并查集)
传送门 cdq分治好题. 对于一条边,如果加上它刚好连通的话,那么删掉它会有两个大集合A,B.于是我们先将B中禁用的边连上,把A中禁用的边禁用,再递归处理A:然后把A中禁用的边连上,把B中禁用的边禁用 ...
- 【CF603E】Pastoral Oddities cdq分治+并查集
[CF603E]Pastoral Oddities 题意:有n个点,依次加入m条边权为$l_i$的无向边,每次加入后询问:当前图是否存在一个生成子图,满足所有点的度数都是奇数.如果有,输出这个生成子图 ...
- BZOJ1997 HNOI2010 平面图判定 planar (并查集判二分图)
题意 判断一个存在哈密顿回路的图是否是平面图. n≤200,m≤10000n\le200,m\le10000n≤200,m≤10000 题解 如果一定存在一个环,那么连的边要么在环里面要么在外面.那么 ...
- 2018.09.30 bzoj4025: 二分图(线段树分治+并查集)
传送门 线段树分治好题. 这道题实际上有很多不同的做法: cdq分治. lct. - 而我学习了dzyo的线段树分治+并查集写法. 所谓线段树分治就是先把操作分成lognlognlogn个连续不相交的 ...
- BZOJ_4025_二分图_线段树按时间分治+并查集
BZOJ_4025_二分图_线段树按时间分治+并查集 Description 神犇有一个n个节点的图.因为神犇是神犇,所以在T时间内一些边会出现后消失.神犇要求出每一时间段内这个图是否是二分图.这么简 ...
随机推荐
- Socket编程中的长连接、短链接以及心跳包机制详解
参考:http://blog.csdn.net/zdwzzu2006/article/details/7723738 一.定义 1.TCP连接 当网络通信时采用TCP协议时,在真正的读写操作之前,se ...
- Tip of the Day
Did you know ... ? You can view all statements within the method where certain exceptions can be cau ...
- (转载)js 快捷键大全,并有简单使用说明
摘要: (转载)原文链接: http://www.cnblogs.com/fire-phoenix/archive/2010/09/28/1837295.html Code highlighting ...
- hadoop(二)
三 Hive和Hbase #安装配置Hbase环境#主要参考https://my.oschina.net/zc741520/blog/388718网站配置的是集群,这里是伪分布,将网站中涉及多个主机的 ...
- python3 验证用户名密码
输入用户名,密码,匹配通过,不匹配报错 import getpass user = input('input username: ') pwd = getpass.getpass('input pas ...
- WeakSelf宏的进化(转载)
我们都知道在防止如block的循环引用时,会使用__weak关键字做如下定义: __weak typeof(self) weakSelf = self; 后来,为了方便,不用每次都要写这样一句固定代码 ...
- 升级ruby
1.安装 RVM RVM:Ruby Version Manager,Ruby版本管理器,包括Ruby的版本管理和Gem库管理(gemset) $ curl -L get.rvm.io | bash - ...
- 设计模式 -- 代理模式 (Proxy Pattern)
定义: 为其他对象提供一种代理以控制对这个对象的访问: 角色: 1,抽象主题类,(接口或者抽象类),抽象真实主题和代理的共有方法(如下Subject类): 2,具体实现的主题类,继承或者实现抽象主题类 ...
- PHP引用操作以及外部操作函数的局部静态变量的方法
通过引用方式在外部操作函数或成员方法内部的静态变量 下面举个简单的例子,说明三个关于引用方面的问题: 1. 参数引用后函数内进行类型转换同样是地址操作 2. 参数引用后再传递给其他函数时需要再次添加引 ...
- dplyr 数据操作 常用函数(3)
接下了我们继续了解dplyr中有用的函数 1.if_else() if_else主要用于在数据做判断用 x<-data.frame(id=1:6, name=c("wang" ...