1. 程式人生 > >【刷題】BZOJ 4025 二分圖

【刷題】BZOJ 4025 二分圖

-o 情況 問題 split i+1 else find spl for

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。

Solution

這題害了我一天
首先看怎麽靜態判能不能二分,一條一條邊加進去,如果這條邊加上會變成一個環,並且這個環還是奇環,那就不能二分;反之,可以

然後看動態的,動態的麻煩就在刪除,因為可能把一條樹邊刪掉之後,會有一條非樹邊代替它變成一條樹邊,這個做不了;所以就弄一個LCT維護這個樹,維護這個圖以刪除時間為關鍵字的最大生成樹,這樣就不會有上述情況發生了
然後按照套路,離線解決
(PS:從早上開始調,一直調到晚上,開始的時候造數據的程序還寫錯了,會使標程RE,然後有一次其實改對了,但因為數據造錯,一直拍不上,結果就和gt拿了一個正確的程序調了半個小時)

#include<bits/stdc++.h>
#define ui unsigned int
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long const int MAXN=100000+10,MAXM=200000+10,inf=0x3f3f3f3f; int n,m,tT,V[MAXN+MAXM],sum,f[MAXN+MAXM]; struct edge{ int u,v; }; edge side[MAXM]; struct data{ int opt,val,t,id; inline bool operator < (const data &A) const { return t<A.t||t==A.t&&opt>A.opt; }; }; data p[MAXM<<1]; #define lc(x) ch[(x)][0] #define rc(x) ch[(x)][1] struct LCT{ int ch[MAXN+MAXM][2],fa[MAXN+MAXM],rev[MAXN+MAXM],Mn[MAXN+MAXM],id[MAXN+MAXM],stack[MAXN+MAXM],cnt,val[MAXN+MAXM],size[MAXN+MAXM]; inline void init() { memset(Mn,inf,sizeof(Mn)); memset(val,inf,sizeof(val)); } inline bool nroot(int x) { return lc(fa[x])==x||rc(fa[x])==x; } inline void reverse(int x) { std::swap(lc(x),rc(x)); rev[x]^=1; } inline void pushup(int x) { size[x]=size[lc(x)]+size[rc(x)]+1; Mn[x]=val[x],id[x]=x; if(Mn[lc(x)]<Mn[x])Mn[x]=Mn[lc(x)],id[x]=id[lc(x)]; if(Mn[rc(x)]<Mn[x])Mn[x]=Mn[rc(x)],id[x]=id[rc(x)]; } inline void pushdown(int x) { if(rev[x]) { if(lc(x))reverse(lc(x)); if(rc(x))reverse(rc(x)); rev[x]=0; } } inline void rotate(int x) { int f=fa[x],p=fa[f],c=(rc(f)==x); if(nroot(f))ch[p][rc(p)==f]=x; fa[ch[f][c]=ch[x][c^1]]=f; fa[ch[x][c^1]=f]=x; fa[x]=p; pushup(f); pushup(x); } inline void splay(int x) { cnt=0; stack[++cnt]=x; for(register int i=x;nroot(i);i=fa[i])stack[++cnt]=fa[i]; while(cnt)pushdown(stack[cnt--]); for(register int y=fa[x];nroot(x);rotate(x),y=fa[x]) if(nroot(y))rotate((lc(y)==x)==(lc(fa[y])==y)?y:x); pushup(x); } inline void access(int x) { for(register int y=0;x;x=fa[y=x])splay(x),rc(x)=y,pushup(x); } inline int findroot(int x) { access(x);splay(x); while(lc(x))pushdown(x),x=lc(x); splay(x); return x; } inline void makeroot(int x) { access(x);splay(x);reverse(x); } inline void split(int x,int y) { makeroot(x);access(y);splay(y); } inline void link(int x,int y) { makeroot(x);fa[x]=y; } inline void cut(int x,int y) { split(x,y);fa[x]=lc(y)=0;pushup(y); } }; LCT T; #undef lc #undef rc template<typename T> inline void read(T &x) { T data=0,w=1; char ch=0; while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar(); if(ch=='-')w=-1,ch=getchar(); while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar(); x=data*w; } template<typename T> inline void write(T x,char c='\0') { if(x<0)putchar('-'),x=-x; if(x>9)write(x/10); putchar(x%10+'0'); if(c!='\0')putchar(c); } template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);} template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);} template<typename T> inline T min(T x,T y){return x<y?x:y;} template<typename T> inline T max(T x,T y){return x>y?x:y;} inline void add(int now) { int u=side[p[now].id].u,v=side[p[now].id].v,sn=p[now].id+n; if(u==v) { f[sn-n]=1;sum++; return ; } if(T.findroot(u)!=T.findroot(v))T.val[sn]=p[now].val,T.link(sn,u),T.link(sn,v),V[sn-n]=1; else { T.split(u,v); int so=T.id[v],nt=T.size[v]>>1; if(p[now].val>T.Mn[v]) { if(!(nt&1))sum++,f[so-n]=1; T.cut(so,side[so-n].u); T.cut(so,side[so-n].v); T.val[sn]=p[now].val; T.link(sn,u); T.link(sn,v); V[so-n]=0;V[sn-n]=1; } else if(!(nt&1))sum++,f[sn-n]=1; } } inline void del(int now) { int sn=p[now].id+n; sum-=f[sn-n]; if(V[sn-n]) { V[sn-n]=f[sn-n]=0; T.cut(sn,side[sn-n].u);T.cut(sn,side[sn-n].v); } else f[sn-n]=0; } int main() { read(n);read(m);read(tT); for(register int i=1;i<=m;++i) { int u,v,st,ed; read(u);read(v);read(st);read(ed); side[i].u=u;side[i].v=v; p[i].t=st;p[i].val=ed;p[i].id=i;p[i].opt=1; p[i+m].t=ed;p[i+m].id=i;p[i+m].opt=0; } std::sort(p+1,p+m*2+1); T.init(); for(register int i=1,j=1;i<=tT;++i) { for(;p[j].t<i&&j<=m*2;++j) if(p[j].opt)add(j); else del(j); if(sum)puts("No"); else puts("Yes"); } return 0; }

【刷題】BZOJ 4025 二分圖