BZOJ4025 二分图 分治 并查集 二分图 带权并查集按秩合并
原文链接http://www.cnblogs.com/zhouzhendong/p/8683831.html
题目传送门 - BZOJ4025
题意
有$n$个点,有$m$条边。有$T$个时间段。其中第$i$条边连接节点$x_i,y_i$,并且在$start_i$时刻出现,在$end_i$时刻消失。问每一个时刻的图是不是二分图。
$n\leq 10^5,m\leq 2\times 10^5,T\leq 10^5$
题解
真是一道好题。
做这题我才发现我从来没写过按秩合并的并查集QAQ。
先考虑按照时间二分。
对于某一段时间,我们可以把所有在当前时间段一直出现的边连起来。这个可以用按秩合并的带权并查集维护。(注意子程序退出的时候要撤销所有操作)
如果在加边的过程中,发现冲突,那么该区间全部都是NO了。
否则把除了完全覆盖当前区间的边之外的,对左区间有关的扔到左边,对右区间有关的扔到右边。然后递归子区间处理。
注意区间长度为1的时候不要再递归下去了,会RE的。
具体实现参见代码。
我们来分析一下为什么复杂度是对的。
首先考虑空间复杂度。
考虑每一层递归的时候最多有$O(n)$条边,最多有$O(\log n)$层,所以空间复杂度为$O(n\log n)$。
考虑时间复杂度。
我们发现主要的复杂度在边的处理上。一条边在多少个时间段被连接,就是他对总时间复杂度的贡献。
显然每一条边在同一个区间只会被连接一下,但是要按秩合并并查集,所以单次复杂度为$O(\log n)$。考虑到一个边最多在$O(\log n)$个区间被连接(和线段树区间覆盖的原理差不多吧)。所以每一条边最多贡献$O(\log^2 n)$的时间复杂度。所以有$m$条边,显然$m$的上限和$n$同阶,当他是$n$就可以了,所以总的时间复杂度为$O(n\log^2 n)$。
代码
#include <bits/stdc++.h>
using namespace std;
const int N=200005;
struct Edge{
int x,y,s,t;
void get(){
scanf("%d%d%d%d",&x,&y,&s,&t),s++;
}
}e[N];
int n,m,T,ans[N];
vector <int> x;
struct UFset{
int n,fa[N],depth[N],d[N],stack[N],top;
void init(int _n){
n=_n;
for (int i=1;i<=n;i++)
fa[i]=i;
memset(depth,0,sizeof depth);
memset(d,0,sizeof d);
top=0;
}
int getf(int x){
while (fa[x]!=x)
x=fa[x];
return x;
}
int getdis(int x){
int ans=0;
while (fa[x]!=x)
ans^=d[x],x=fa[x];
return ans;
}
bool Merge(int x,int y){
int D=getdis(x)^getdis(y)^1;
x=getf(x),y=getf(y);
if (x==y)
return D==0;
if (depth[x]<depth[y])
swap(x,y);
if (depth[x]==depth[y])
depth[x]++,stack[++top]=-x;
fa[y]=x,d[y]=D,stack[++top]=y;
return 1;
}
void Split(int time){
while (top>time){
int x=stack[top--];
if (x<0)
depth[-x]--;
else
fa[x]=x,d[x]=0;
}
}
}s;
void solve(int L,int R,vector <int> &now){
if (now.size()==0)
return;
vector <int> Lpart,Rpart;
Lpart.clear(),Rpart.clear();
int time=s.top,mid=(L+R)>>1;
for (int i=0;i<now.size();i++){
int id=now[i];
if (e[id].s<=L&&e[id].t>=R){
if (!s.Merge(e[id].x,e[id].y)){
for (int j=L;j<=R;j++)
ans[j]=0;
s.Split(time);
return;
}
}
else {
if (e[id].t<=mid)
Lpart.push_back(id);
else if (e[id].s>mid)
Rpart.push_back(id);
else if (e[id].s<=mid&&e[id].t>mid)
Lpart.push_back(id),Rpart.push_back(id);
}
}
if (L==R){
s.Split(time);
return;
}
solve(L,mid,Lpart);
solve(mid+1,R,Rpart);
s.Split(time);
}
int main(){
scanf("%d%d%d",&n,&m,&T);
x.clear();
for (int i=1;i<=m;i++)
e[i].get(),x.push_back(i);
for (int i=1;i<=T;i++)
ans[i]=1;
s.init(n);
solve(1,T,x);
for (int i=1;i<=T;i++)
puts(ans[i]?"Yes":"No");
return 0;
}
BZOJ4025 二分图 分治 并查集 二分图 带权并查集按秩合并的更多相关文章
- 并查集模板 && 带权并查集模板
不带权: ]; void init(void) { ;i<=n;i++) f[i]=i; } int fd(int x) { return f[x]==x?x:fd[x]=fd(f[x]); } ...
- 浅谈并查集&种类并查集&带权并查集
并查集&种类并查集&带权并查集 前言: 因为是学习记录,所以知识讲解+例题推荐+练习题解都是放在一起的qvq 目录 并查集基础知识 并查集基础题目 种类并查集知识 种类并查集题目 并查 ...
- BZOJ4025 二分图 线段树分治、带权并查集
传送门 如果边不会消失,那么显然可以带权并查集做(然后发现自己不会写带权并查集) 但是每条边有消失时间.这样每一条边产生贡献的时间对应一段区间,故对时间轴建立线段树,将每一条边扔到线段树对应的点上. ...
- hdu 1829 &poj 2492 A Bug's Life(推断二分图、带权并查集)
A Bug's Life Time Limit: 15000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) To ...
- CodeForces - 687D: Dividing Kingdom II (二分图&带权并查集)
Long time ago, there was a great kingdom and it was being ruled by The Great Arya and Pari The Great ...
- UVA - 10004 Bicoloring(判断二分图——交叉染色法 / 带权并查集)
d.给定一个图,判断是不是二分图. s.可以交叉染色,就是二分图:否则,不是. 另外,此题中的图是强连通图,即任意两点可达,从而dfs方法从一个点出发就能遍历整个图了. 如果不能保证从一个点出发可以遍 ...
- codeforces 687D Dividing Kingdom II 带权并查集(dsu)
题意:给你m条边,每条边有一个权值,每次询问只保留编号l到r的边,让你把这个图分成两部分 一个方案的耗费是当前符合条件的边的最大权值(符合条件的边指两段点都在一个部分),问你如何分,可以让耗费最小 分 ...
- A Bug's Life POJ - 2492 (种类或带权并查集)
这个题目的写法有很多,用二分图染色也可以写,思路很好想,这里我们用关于并查集的两种写法来做. 题目大意:输入x,y表示x和y交配,然后判断是否有同性恋. 1 带权并查集: 我们可以用边的权值来表示一种 ...
- Codeforces 1499G - Graph Coloring(带权并查集+欧拉回路)
Codeforces 题面传送门 & 洛谷题面传送门 一道非常神仙的题 %%%%%%%%%%%% 首先看到这样的设问,做题数量多一点的同学不难想到这个题.事实上对于此题而言,题面中那个&quo ...
随机推荐
- MySQL按字段排序后取序号
1 前言 项目中排行榜刚好需要查数据库表然后给出编号,方案一,可以按条件查找出来,然后再按数组序号给编号,但是如果要查表出来直接看,就不太够用了:方案二,就是用代码帮忙编号.参考了网上一些代码,然后发 ...
- Jquery分享插件
效果图如下: 代码如下: <!DOCTYPE HTML> <html style="padding-bottom: 54px;"> <head> ...
- SpringMvc + Jsp+ 富文本 kindeditor 进行 图片ftp上传nginx服务器 实现
一:html 原生态的附件上传 二:实现逻辑分析: 1.1.1 需求分析 Common.js 1.绑定事件 2.初始化参数 3.上传图片的url: /pic/upload 4.上图片参数名称: upl ...
- Confluence 6 嵌入的 H2 数据库
为了让你的 Confluence 在安装成功后就可以使用而不需要使用任何外部的数据库,Confluence 使用一个嵌入的 H2 数据库. 当你选择对 Confluence 进行评估和测试的时候,H2 ...
- ios 输入框问题
去除ios输入框阴影 input,textarea{-webkit-appearance:none; outline: none; } ios有边框时设置boder-radius:0: 去除默认圆角问 ...
- java对之前的复习
日期:2018.7.29 星期日 博客期:003 我知道我实在是不想写博客,因为要做很多的准备啊!因为还要准备靠驾驶本,所以两边都要学!要不这次来总结总结驾驶员知识?还是算了吧!今天来总结一下学到的J ...
- laravel 路由缓存
使用路由缓存之前,需要知晓路由缓存只能用于控制器路由,不能用于闭包路由,如果路由定义中包含闭包路由将无法进行路由缓存,只有将所有路由定义转化为控制器路由或资源路由后才能执行路由缓存命令: php ar ...
- 关于JDBC的总结
1. Spring JDBC子框架是什么 答:就是一个Spring框架内置的持久层框架.既然是一个持久层框架,作用就是对数据库增删改查!! 2. SpringJDBC是使用声明类操作数据库的? 答:J ...
- 多线程相关-ThreadPoolExecutor
应用层面: ThreadPoolExecutor: 创建多线程池执行器:new ThreadPoolExecutor(),创建方法最终都是走的以下这个构造方法: /** * Creates a new ...
- git无法pull仓库refusing to merge unrelated histories (拒绝合并不相关仓库)
原文地址 https://blog.csdn.net/lindexi_gd/article/details/52554159 本文讲的是把git在最新2.9.2,合并pull两个不同的项目,出现的问题 ...