bzoj4025 二分图
来源:互联网 发布:长安app软件下载 编辑:程序博客网 时间:2024/06/07 05:08
题目链接:bzoj4025
题目大意:
神犇有一个n个节点的图。因为神犇是神犇,所以在T时间内一些边会出现后消失。神犇要求出每一时间段内这个图是否是二分图。这么简单的问题神犇当然会做了,于是他想考考你。
题解:
cdq+并查集判奇环
二分图,不存在奇环的图就叫二分图。所以用带权并查集来判断奇环。为了(?),按秩合并且不用路径压缩(方便还原并查集)。按秩合并的话就是有个rank[i]值表示该集的高度,每次合并就把rank小的合到大的那里,使复杂度最小。
那么判断的时候对于一边上的两点,若不在一个并查集那么肯定不会构成环,若在的话,就getdistance判断是否是奇环。
分治过程:
1、处理完全符合分治区间时间段的所有边合并并判埋是否有奇环。若有的话,该时间段的都不是二分图了,就可以退了...
2、其余不完全符合区间的都在左边就弄到左边,都在右边就弄到右边。若跨区间,则把左半部分弄到左边,右半部分到右边
3、若分治到底,就说明这个时间段是二分图
4、没有到底就分治左边,分治右边啊
5、把并查集恢复至初始的样子
#include<cstdio>#include<cstdlib>#include<cstring>#include<vector>#include<iostream>#include<algorithm>using namespace std;#define maxn 201000struct node {int x,y,s,t;};vector<node> S;int tp,sta1[maxn];bool sta2[maxn];int rk[maxn],fa[maxn],d[maxn],ans[maxn];int ffind(int x){while (x!=fa[x]) x=fa[x];return x;}void merge(int fx,int fy,int c){if (rk[fx]>rk[fy]) {sta1[++tp]=fy;sta2[tp]=1;fa[fy]=fx,d[fy]=c;}else if (rk[fx]<rk[fy]) {sta1[++tp]=fx;sta2[tp]=1;fa[fx]=fy,d[fx]=c;}else{rk[fx]++;sta1[++tp]=fy;sta2[tp]=0;fa[fy]=fx;d[fy]=c;}}int getd(int x){int ans=0;while (x!=fa[x]) ans^=d[x],x=fa[x];return ans;}void solve(int l,int r,vector<node> M)//int ll,int rr{int i,mid=(l+r)>>1,now=tp;vector<node> ll,rr;for (i=0;i<M.size();i++){node a=M[i];if (a.s==l && a.t==r){ int x=a.x,y=a.y; int fx=ffind(x),fy=ffind(y); int c=getd(x)^getd(y)^1; if (fx!=fy) merge(fx,fy,c); else if (c&1) { for (int j=l;j<=r;j++) ans[j]=0; while (now!=tp) { if (!sta2[tp]) rk[sta1[tp]]--; fa[sta1[tp]]=sta1[tp];d[sta1[tp]]=0;tp--; } return; }}else if (a.t<=mid) ll.push_back(a);else if (a.s>mid) rr.push_back(a);else{node b=a;b.t=mid;ll.push_back(b);b=a;b.s=mid+1;rr.push_back(b);}}if (l==r) ans[l]=1;else solve(l,mid,ll),solve(mid+1,r,rr);while (now!=tp) {if (!sta2[tp]) rk[sta1[tp]]--;fa[sta1[tp]]=sta1[tp];d[sta1[tp]]=0;tp--;}}int main(){freopen("a.in","r",stdin);freopen("a.out","w",stdout);int n,m,T,i;tp=0;scanf("%d%d%d",&n,&m,&T);//T段时间for (i=1;i<=n;i++) d[i]=0,fa[i]=i;for (i=1;i<=m;i++){node t;scanf("%d%d%d%d",&t.x,&t.y,&t.s,&t.t);t.s++;if (t.s<=t.t) S.push_back(t);//s时刻出现t时刻消失即于第s+1时段~第t时段存在}for (i=1;i<=T;i++) ans[i]=1;solve(1,T,S);for (i=1;i<=T;i++) if (ans[i]) printf("Yes\n");else printf("No\n");return 0;}
0 0
- 【BZOJ4025】二分图
- 【bzoj4025】【二分图】【lct】
- [bzoj4025]二分图
- [BZOJ4025][LCT]二分图
- bzoj4025 二分图
- [bzoj4025]二分图 解题报告
- [BZOJ4025]二分图(lct)
- BZOJ4025:二分图 ((CDQ分治+并查集)/LCT)
- bzoj4025二分图 线段树分治+并查集
- BZOJ4025: 二分图(线段树+并查集)
- BZOJ4025(LCT+LCT+LinkCutTree)
- 二分图
- 二分图
- 二分图
- 二分图
- 二分图
- 二分图
- 二分图
- Mysql Window 免安装版
- oracle 每日一题-avg求平均值
- 为什么 Laravel 5 这么好一个框架国内开发者都不去用?
- PC端自适应布局
- Oracle数据库表分区
- bzoj4025 二分图
- TCP-IP协议族(二) HTTP报文头解析
- 决策树 - 算法基本实现
- 2017 cocoapods 安装 1.2.0
- 解决android 两次调用DatePickerDialog.onDateSet()的方法
- 简单工厂的设计模式
- Android Studio 使用海马玩模拟器运行项目
- [Leetcode] #46#47 Permutations I & II
- 在linux下执行定时任务运行一个java程序