[HDU5354]Bipartite Graph(CDQ分治+并查集)
经典动态二分图问题。
考虑solve(l,r)分治成l,mid和mid+1,r。先将区间[mid+1,r]中的点全部加入图中,若此时存在奇环则ans[l..mid]全部为0,否则递归到左边。
递归完左边后将右边的点全部删去,左边点全部加入,按同样的方法处理右边。
判断奇环使用可撤销带权并查集,注意多组数据不要用memset。
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #define rep(i,l,r) for (int i=(l); i<=(r); i++) 5 using namespace std; 6 7 const int N=200010; 8 int T,n,m,top,cnt,u,v; 9 int fa[N],sz[N],d[N],ans[N],h[N],nxt[N],to[N]; 10 struct P{ int a,b,c; }s[3*N]; 11 struct S{ int x,y; }; 12 void add(int u,int v){ to[++cnt]=v; nxt[cnt]=h[u]; h[u]=cnt; } 13 14 void init(){ cnt=0; rep(i,1,n) fa[i]=i,sz[i]=1,d[i]=0,h[i]=0; } 15 16 S get(int x){ 17 if (fa[x]==x) return (S){x,0}; 18 S t=get(fa[x]); return (S){t.x,t.y^d[x]}; 19 } 20 21 void uni(int x,int y){ 22 int t1=get(x).y; x=get(x).x; 23 int t2=get(y).y; y=get(y).x; 24 if (sz[x]<sz[y]) swap(x,y); 25 s[++top]=(P){0,y,y}; s[++top]=(P){1,x,sz[x]}; s[++top]=(P){2,y,0}; 26 fa[y]=x; d[y]=t1^t2^1; sz[x]+=sz[y]; 27 } 28 29 void cancel(int x){ 30 if (s[x].a==0) fa[s[x].b]=s[x].c; 31 if (s[x].a==1) sz[s[x].b]=s[x].c; 32 if (s[x].a==2) d[s[x].b]=s[x].c; 33 } 34 35 void solve(int l,int r){ 36 if (l==r) { ans[l]=1; return; } 37 int mid=(l+r)>>1,tmp=top; bool flag=0; 38 rep(u,mid+1,r) 39 for (int i=h[u]; i; i=nxt[i]){ 40 int v=to[i]; 41 if (v>=l && v<=mid) continue; 42 if (get(u).x!=get(v).x) uni(u,v); 43 else if (get(u).y==get(v).y) { flag=1; break; } 44 } 45 if (flag) rep(i,l,mid) ans[i]=0; else solve(l,mid); 46 while (top>tmp) cancel(top--); flag=0; 47 rep(u,l,mid) 48 for (int i=h[u]; i; i=nxt[i]){ 49 int v=to[i]; 50 if (v>mid && v<=r) continue; 51 if (get(u).x!=get(v).x) uni(u,v); 52 else if (get(u).y==get(v).y) { flag=1; break; } 53 } 54 if (flag) rep(i,mid+1,r) ans[i]=0; else solve(mid+1,r); 55 while (top>tmp) cancel(top--); 56 } 57 58 int main(){ 59 freopen("hdu5354.in","r",stdin); 60 freopen("hdu5354.out","w",stdout); 61 for (scanf("%d",&T); T--; ){ 62 scanf("%d%d",&n,&m); init(); 63 rep(i,1,m) scanf("%d%d",&u,&v),add(u,v),add(v,u); 64 solve(1,n); 65 rep(i,1,n) printf("%d",ans[i]); puts(""); 66 } 67 return 0; 68 }