1. 程式人生 > >[BZOJ4025] 二分圖 LCT/(線段樹分治+並查集)

[BZOJ4025] 二分圖 LCT/(線段樹分治+並查集)

4025: 二分圖

Time Limit: 20 Sec  Memory Limit: 512 MB
Submit: 2667  Solved: 989
[Submit][Status][Discuss]

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做法

 其實就是求是否有奇環。先求出最小生成樹,隨後根據非樹邊兩點間的距離得出是否有奇環。

lct維護以邊消失時間為權值的最大生成樹。這樣可以保證所有已經進入集合的非樹邊都不會從集合中出來再次成為樹邊。
從小到達列舉時間進行加邊和刪邊。
加邊判奇環,更新最大生成樹和集合.
刪邊如果是最大生成樹裡的邊就在lct中刪掉。否則僅在集合中刪掉即可。

  1 #include<iostream>
  2 #include<cstdlib>
  3 #include<cmath>
  4
#include<cstdio> 5 #include<algorithm> 6 #include<cstring> 7 #define maxn 400001 8 using namespace std; 9 inline int read() { 10 char ch=getchar();int x=0,f=1; 11 for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-1; 12 for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0'; 13 return x*f; 14 } 15 int n,m,T,ont[maxn*2],jh[maxn*2],tot,val[maxn*2]; 16 struct Edge { 17 int to[maxn*4],nxt[maxn*4],head[maxn*2],cnt; 18 Edge(){memset(head,-1,sizeof(head));cnt=0;} 19 void add(int u,int v) {to[cnt]=v;nxt[cnt]=head[u];head[u]=cnt++;} 20 }e1,e2; 21 struct ASK {int u,v,w;}a[maxn*2]; 22 struct LCT { 23 struct Data { 24 int son[2],sz,fa,rev,mn; 25 }t[maxn*2]; 26 bool isrt(int x) {return t[t[x].fa].son[0]!=x&&t[t[x].fa].son[1]!=x;} 27 void pushdown(int x) { 28 if(t[x].rev) { 29 swap(t[x].son[0],t[x].son[1]); 30 t[t[x].son[0]].rev^=1;t[t[x].son[1]].rev^=1; 31 t[x].rev=0; 32 } 33 } 34 void pushup(int x) { 35 t[x].sz=t[t[x].son[0]].sz+t[t[x].son[1]].sz+(x>n); 36 t[x].mn=x; 37 if(val[t[t[x].son[0]].mn]<val[t[x].mn]) t[x].mn=t[t[x].son[0]].mn; 38 if(val[t[t[x].son[1]].mn]<val[t[x].mn]) t[x].mn=t[t[x].son[1]].mn; 39 } 40 void rotate(int x) { 41 int y=t[x].fa,z=t[y].fa; 42 bool l=(t[y].son[1]==x),r=l^1; 43 if(!isrt(y)) t[z].son[t[z].son[1]==y]=x; 44 t[x].fa=z;t[y].fa=x;t[t[x].son[r]].fa=y; 45 t[y].son[l]=t[x].son[r];t[x].son[r]=y; 46 pushup(y);pushup(x); 47 } 48 void push(int x) { 49 if(!isrt(x)) push(t[x].fa); 50 pushdown(x); 51 } 52 void splay(int x) { 53 push(x); 54 while(!isrt(x)) { 55 int y=t[x].fa,z=t[y].fa; 56 if(!isrt(y)) { 57 if(t[y].son[0]==x^t[z].son[0]==y) rotate(x); 58 else rotate(y); 59 } 60 rotate(x); 61 } 62 } 63 void access(int x) {for(int pre=0;x;pre=x,x=t[x].fa) {splay(x),t[x].son[1]=pre;pushup(x);}} 64 void makert(int x) {access(x);splay(x);t[x].rev^=1;} 65 void link(int x,int y) {makert(x);t[x].fa=y;} 66 void cut(int x,int y) {makert(x);access(y);splay(y);t[y].son[0]=t[x].fa=0;} 67 int find(int x) {access(x);splay(x);while(t[x].son[0]) x=t[x].son[0];return x;} 68 }lct; 69 void insert(int x,int u,int v,int w) { 70 if(u==v) {jh[x]=1;tot++;return;} 71 if(lct.find(u)!=lct.find(v)) { 72 73 ont[x]=1;lct.link(u,n+x);lct.link(v,n+x); 74 } 75 else { 76 lct.makert(v);lct.access(u);lct.splay(u);int tmp=lct.t[u].mn-n; 77 if(a[tmp].w<a[x].w) { 78 if(!(lct.t[u].sz&1)) {jh[tmp]=1;tot++;} 79 lct.cut(a[tmp].u,tmp+n);lct.cut(a[tmp].v,tmp+n); 80 lct.link(u,n+x);lct.link(v,n+x); 81 ont[tmp]=0;ont[x]=1; 82 } 83 else { 84 if(!(lct.t[u].sz&1)) {jh[x]=1;tot++;} 85 } 86 } 87 } 88 void del(int x,int u,int v,int w) { 89 if(ont[x]) {lct.cut(u,x+n);lct.cut(v,x+n);} 90 else if(jh[x]) tot--; 91 } 92 int main() { 93 n=read(),m=read(),T=read(); 94 memset(val,27,sizeof(val)); 95 for(int i=1;i<=n;i++) lct.t[i].mn=i; 96 for(int i=1;i<=m;i++) { 97 a[i].u=read(),a[i].v=read();int s=read(),t=read(); 98 e1.add(s,i);e2.add(t,i);a[i].w=t;lct.t[n+i].sz=1;lct.t[n+i].mn=n+i;val[n+i]=t; 99 } 100 for(int i=0;i<T;i++) { 101 for(int j=e1.head[i];j>=0;j=e1.nxt[j]) { 102 int to=e1.to[j]; 103 insert(to,a[to].u,a[to].v,a[to].w); 104 } 105 for(int j=e2.head[i];j>=0;j=e2.nxt[j]) { 106 int to=e2.to[j]; 107 del(to,a[to].u,a[to].v,a[to].w); 108 } 109 if(!tot) printf("Yes\n"); 110 else printf("No\n"); 111 } 112 return 0; 113 } 114 /* 115 45365 116 57727 117 */
View Code