[BZOJ4025] 二分图 LCT/(线段树分治+并查集)
4025: 二分图
Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 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
1 2 0 2
2 3 0 3
1 3 1 2
Sample Output
Yes
No
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 */
O(∩_∩)O~ (*^__^*) 嘻嘻…… O(∩_∩)O哈哈~