【BZOJ4025】二分图
来源:互联网 发布:淘宝联盟佣金是谁给的 编辑:程序博客网 时间:2024/05/22 14:14
Description
神犇有一个n个节点的图。因为神犇是神犇,所以在T时间内一些边会出现后消失。神犇要求出每一时间段内这个图是否是二分图。这么简单的问题神犇当然会做了,于是他想考考你。
Input
输入数据的第一行是三个整数n,m,T。
第2行到第m+1行,每行4个整数u,v,start,end。第i+1行的四个整数表示第i条边连接u,v两个点,这条边在start时刻出现,在第end时刻消失。
Output
输出包含T行。在第i行中,如果第i时间段内这个图是二分图,那么输出“Yes”,否则输出“No”,不含引号。
Sample Input
3 3 3
1 2 0 2
2 3 0 3
1 3 1 2
Sample Output
Yes
No
Yes
HINT
样例说明:
0时刻,出现两条边1-2和2-3。
第1时间段内,这个图是二分图,输出Yes。
1时刻,出现一条边1-3。
第2时间段内,这个图不是二分图,输出No。
2时刻,1-2和1-3两条边消失。
第3时间段内,只有一条边2-3,这个图是二分图,输出Yes。
数据范围:
n<=100000,m<=200000,T<=100000,1<=u,v<=n,0<=start<=end<=T。
Source
可以考虑用LCT维护一个以删除时间为关键字的最大生成树
同时维护一个边的集合表示在这个集合中的边如果在图中则一定不是二分图(就用一个数组就好了_ (:зゝ∠) _)
由二分图的定义可知 二分图是没有奇环的图
然后对于那两种操作:
对于插入,如果边的两端点不连通,连边后一定不会形成环,直接link上
如果已经联通,加边后一定存在非树边.此时如果加边后会形成奇环,就把这条边加入上述集合
删除时候对于树边直接删除,非树边在集合中则直接从集合中删除
其实也可以用cdq+并查集来搞
具体做法没考虑过但是可以看Po姐姐的Blog
PoPoQQQ
P.S.颓了那么久终于开始干正事了..
#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#define MAXN 100010#define GET (ch>='0'&&ch<='9')#define MAXINT 0x3f3f3f3fusing namespace std;int n,m,T,Top,cnt;int sta[MAXN<<1],top;int In[MAXN<<1],on[MAXN<<1];struct splay{ int ch[2],fa,minn,st,sum,val; bool rev;}tree[MAXN<<2];inline void in(int &x){ char ch=getchar();x=0; while (!GET) ch=getchar(); while (GET) x=x*10+ch-'0',ch=getchar();}struct edge{ int u,v,w;}e[MAXN<<1];struct Edge{ int to; Edge *next;}E[MAXN<<2],*prev1[MAXN],*prev2[MAXN];inline void insert1(int u,int v) {E[++Top].to=v;E[Top].next=prev1[u];prev1[u]=&E[Top];}inline void insert2(int u,int v) {E[++Top].to=v;E[Top].next=prev2[u];prev2[u]=&E[Top];}inline bool is_root(int x){ return tree[tree[x].fa].ch[0]!=x&&tree[tree[x].fa].ch[1]!=x;}inline void push_down(int x){ if (tree[x].rev) { tree[tree[x].ch[0]].rev^=1,tree[tree[x].ch[1]].rev^=1; swap(tree[x].ch[0],tree[x].ch[1]); } tree[x].rev=0;}inline void push_up(int x){ tree[x].minn=tree[x].val;tree[x].st=x;tree[x].sum=x>n; if (tree[x].ch[0]) { if (tree[tree[x].ch[0]].minn<tree[x].minn) tree[x].minn=tree[tree[x].ch[0]].minn,tree[x].st=tree[tree[x].ch[0]].st; tree[x].sum+=tree[tree[x].ch[0]].sum; } if (tree[x].ch[1]) { if (tree[tree[x].ch[1]].minn<tree[x].minn) tree[x].minn=tree[tree[x].ch[1]].minn,tree[x].st=tree[tree[x].ch[1]].st; tree[x].sum+=tree[tree[x].ch[1]].sum; }}inline void rot(int x){ int y=tree[x].fa,z=tree[y].fa,l,r; l=(tree[y].ch[1]==x);r=l^1; if (!is_root(y)) tree[z].ch[tree[z].ch[1]==y]=x; tree[tree[x].ch[r]].fa=y;tree[y].fa=x;tree[x].fa=z; tree[y].ch[l]=tree[x].ch[r];tree[x].ch[r]=y; push_up(y);push_up(x);}inline void Splay(int x){ top=0;sta[++top]=x; for (int i=x;!is_root(i);i=tree[i].fa) sta[++top]=tree[i].fa; while (top) push_down(sta[top--]); while (!is_root(x)) { int y=tree[x].fa,z=tree[y].fa; if (!is_root(y)) { if ((tree[y].ch[0]==x)^(tree[z].ch[0]==y)) rot(x); else rot(y); } rot(x); }}inline void access(int x){ for (int i=0;x;i=x,x=tree[x].fa) Splay(x),tree[x].ch[1]=i,push_up(x);}inline void make_root(int x){ access(x);Splay(x);tree[x].rev^=1;}inline void link(int x,int y){ make_root(x);tree[x].fa=y;}inline void cut(int x,int y){ make_root(x);access(y);Splay(y);tree[y].ch[0]=tree[x].fa=0;push_up(y);}inline void split(int x,int y){ make_root(x);access(y);Splay(y);}inline int find_root(int x){ /*access(x);Splay(x); while (tree[x].ch[0]) x=tree[x].ch[0];*/ for (access(x),Splay(x);tree[x].ch[0];x=tree[x].ch[0]); return x;}inline void ins(int x){ int u=e[x].u,v=e[x].v; if (u==v) {In[x]=1;cnt++;return;} if (find_root(u)!=find_root(v)) on[x]=1,link(u,x+n),link(v,x+n); else { split(u,v);int y=tree[v].st-n; if (e[y].w<e[x].w) { if (tree[v].sum&1^1) In[y]=1,cnt++; cut(e[y].u,y+n);cut(e[y].v,y+n);link(u,x+n);link(v,x+n); on[y]=0;on[x]=1; } else if (tree[v].sum&1^1) In[x]=1,cnt++; }}inline void del(int x){ if (on[x]) cut(e[x].u,x+n),cut(e[x].v,x+n); else if (In[x]) cnt--;}int main(){ in(n);in(m);in(T);int s,t; for (int i=1;i<=n;i++) tree[i].val=tree[i].minn=MAXINT,tree[i].st=i; for (int i=1;i<=m;i++) { in(e[i].u);in(e[i].v);in(s);in(t);e[i].w=t; insert1(s,i);insert2(t,i); tree[i+n].val=tree[i+n].minn=t;tree[i+n].st=i+n;tree[i+n].sum=1; } for (int x=0;x<T;x++) { for (Edge *i=prev1[x];i;i=i->next) ins(i->to); for (Edge *i=prev2[x];i;i=i->next) del(i->to); puts(cnt?"No":"Yes"); }}
- 【BZOJ4025】二分图
- 【bzoj4025】【二分图】【lct】
- [bzoj4025]二分图
- [BZOJ4025][LCT]二分图
- bzoj4025 二分图
- [bzoj4025]二分图 解题报告
- [BZOJ4025]二分图(lct)
- BZOJ4025:二分图 ((CDQ分治+并查集)/LCT)
- bzoj4025二分图 线段树分治+并查集
- BZOJ4025: 二分图(线段树+并查集)
- BZOJ4025(LCT+LCT+LinkCutTree)
- 二分图
- 二分图
- 二分图
- 二分图
- 二分图
- 二分图
- 二分图
- Android中存储目录
- caffe源码c++学习笔记
- Short s1=1; s1=s1+1;会报错吗,编译错误还是运行时错误
- ios9新特性及遇到的一些问题解决方案
- iOS -- 如何封装一个元素是字典的数组
- 【BZOJ4025】二分图
- bash shell提示符字符
- caffe预测、特征可视化python接口调用
- Centos系统下,基于osip2+eXosip2的SIP开发
- 将代码分享到Github
- Rsyslog入库
- android studio运行时报错the selected device is incompatible
- 安装驱动小工具
- 深度学习学习资料