显然一个图是二分图当且仅当图中不存在一个奇环。那么我们用lct维护一个树形结构,如果不存在一条非树边,它连接的两个点在树上的距离为偶数,那么就是一个二分图。那么我们按时间离线之后维护一个树形结构和一个边的集合,集合中的边连接的两点在树上的距离为偶数。那么这个集合为空集则为二分图。
那么如果出现奇环,留下拿一条边在树上就成了问题。显然消失时间晚的可以存在的更久,因此维护一个消失时间的最大生成树(森林)即可。
AC代码如下:
#include<iostream> #include<cstdio> #include<cstring> #define N 100005 #define M 300005 using namespace std; int n,m,cnt,pt,b[M],c[M][2],val[M],sz[M],fa[M],q[M]; bool bo[N<<1],flag[N<<1],rev[M]; struct graph{ int fst[N],nxt[N<<1]; void add(int x,int y){ nxt[y]=fst[x]; fst[x]=y; } }g1,g2; struct node{ int x,y; }a[N<<1]; int read(){ int x=0; char ch=getchar(); while (ch<'0' || ch>'9') ch=getchar(); while (ch>='0' && ch<='9'){ x=x*10+ch-'0'; ch=getchar(); } return x; } bool isrt(int x){ return c[fa[x]][0]!=x && c[fa[x]][1]!=x; } void maintain(int x){ val[x]=x; sz[x]=(x>n)?1:0; if (c[x][0]){ sz[x]+=sz[c[x][0]]; if (b[val[c[x][0]]]<b[val[x]]) val[x]=val[c[x][0]]; } if (c[x][1]){ sz[x]+=sz[c[x][1]]; if (b[val[c[x][1]]]<b[val[x]]) val[x]=val[c[x][1]]; } } void rotate(int x){ int y=fa[x],z=fa[y],l=(c[y][0]==x)?0:1,r=l^1; if (!isrt(y)) if (c[z][0]==y) c[z][0]=x; else c[z][1]=x; fa[x]=z; fa[y]=x; fa[c[x][r]]=y; c[y][l]=c[x][r]; c[x][r]=y; maintain(y); maintain(x); } void pushdown(int x){ if (rev[x]){ swap(c[x][0],c[x][1]); rev[c[x][0]]^=1; rev[c[x][1]]^=1; rev[x]=0; } } void splay(int x){ int y,z,i,tp=1; q[1]=x; for (i=x; !isrt(i); i=fa[i]) q[++tp]=fa[i]; for (i=tp; i; i--) pushdown(q[i]); for (; !isrt(x); rotate(x)){ y=fa[x]; z=fa[y]; if (!isrt(y)) if ((c[y][0]==x)^(c[z][0]==y)) rotate(x); else rotate(y); } } void acss(int x){ int y=0; for (; x; y=x,x=fa[x]){ splay(x); c[x][1]=y; maintain(x); } } void makert(int x){ acss(x); splay(x); rev[x]^=1; } void link(int x,int y){ makert(x); fa[x]=y; } void cut(int x,int y){ makert(x); acss(y); splay(y); fa[x]=c[y][0]=0; maintain(y); } int findrt(int x){ acss(x); splay(x); while (c[x][0]) x=c[x][0]; return x; } void ins(int x,int y,int z){ int u=findrt(x),v=findrt(y); if (x==y){ pt++; flag[z]=1; return; } if (u!=v){ bo[z]=1; link(x,z+n); link(y,z+n); } else{ makert(x); acss(y); splay(y); u=val[y]-n; if (b[u+n]<b[z+n]){ if (!(sz[y]&1)){ pt++; flag[u]=1; } cut(a[u].x,u+n); cut(a[u].y,u+n); link(x,z+n); link(y,z+n); bo[u]=0; bo[z]=1; } else if (!(sz[y]&1)){ pt++; flag[z]=1; } } } int main(){ n=read(); m=read(); cnt=read(); int i,j; for (i=1; i<=n; i++){ val[i]=1; b[i]=1000000000; } for (i=1; i<=m; i++){ a[i].x=read(); a[i].y=read(); g1.add(read()+1,i); g2.add(b[i+n]=read()+1,i); sz[i+n]=1; val[i+n]=i+n; } for (i=1; i<=cnt; i++){ for (j=g1.fst[i]; j; j=g1.nxt[j]) ins(a[j].x,a[j].y,j); for (j=g2.fst[i]; j; j=g2.nxt[j]) if (bo[j]){ cut(a[j].x,j+n); cut(a[j].y,j+n); } else if (flag[j]) pt--; puts(pt?"No":"Yes"); } return 0; }
by lych
2016.5.2