bzoj4025: 二分图
4025: 二分图
Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 1127 Solved: 420
[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。
题解
我们想象对时间轴建一颗线段树,然后对于每一条边有个存在区间,想象线段树区间覆盖。我们从顶走到底的一个点的话,把所有覆盖路径上节点的边都拿出来处理,这样就得到了这个时间点的状态。我们用这样的思想对时间轴进行分治,对于当前处理的某个时间段,首先把完全覆盖这个时间段[l,r]的边给处理一下,然后把开始时间<=mid的找出来递归处理[l,mid],再把结束时间>=mid+1的拿出来递归处理[mid+1,r]
具体实现的方法是可撤销带权并查集,权是到根的路径长度的奇偶,每次处理完一个区间,就把这个区间所有的合并操作全部撤销……这个好像挺简单的网上应该都有……有点像是ahoi2013的某道题。
1 program j01; 2 const maxn=100086; 3 type edge=record u,v,st,ed:longint; end; 4 var e:array[0..2*maxn]of edge; 5 st:array[0..2*maxn]of longint; 6 fa,d:array[0..maxn]of longint; 7 a:array[0..maxn]of boolean; 8 n,m,t,i,top:longint; 9 10 procedure swap(var a,b:edge); 11 var c:edge; 12 begin 13 c:=a;a:=b;b:=c; 14 end; 15 16 procedure swap(var a,b:longint); 17 var c:longint; 18 begin 19 c:=a;a:=b;b:=c; 20 end; 21 22 function ic(var a:longint):longint; 23 begin 24 inc(a);exit(a); 25 end; 26 27 function de(var a:longint):longint; 28 begin 29 de:=a;dec(a); 30 end; 31 32 function find(i:longint):longint; 33 begin 34 while fa[i]<>i do i:=fa[i];exit(i); 35 end; 36 37 function dep(i:longint):boolean; 38 begin 39 dep:=false; 40 while fa[i]<>i do 41 begin 42 dep:=dep xor a[i];i:=fa[i]; 43 end; 44 end; 45 46 procedure union(u,v:longint;dd:boolean); 47 begin 48 if d[u]>d[v] then swap(u,v); 49 if d[u]=d[v] then 50 begin 51 st[ic(top)]:=-v;inc(d[v]); 52 end; 53 st[ic(top)]:=u;fa[u]:=v; 54 a[u]:=dd; 55 end; 56 57 procedure resume(now:longint); 58 begin 59 while top>now do 60 begin 61 if st[top]<0 then dec(d[-st[top]]) else 62 begin 63 fa[st[top]]:=st[top];a[st[top]]:=false; 64 end; 65 dec(top); 66 end; 67 end; 68 69 procedure solve(l,r,m:longint); 70 var mid,i,j,now,fx,fy:longint;dd:boolean; 71 begin 72 now:=top;mid:=(l+r)div 2; 73 i:=1; 74 while i<=m do 75 begin 76 if(e[i].st<=l)and(r<=e[i].ed)then 77 begin 78 fx:=find(e[i].u);fy:=find(e[i].v); 79 dd:=not(dep(e[i].u) xor dep(e[i].v)); 80 if fx<>fy then union(fx,fy,dd) else 81 begin 82 if dd then 83 begin 84 for j:=l to r do writeln('No'); 85 resume(now); 86 exit; 87 end; 88 end; 89 swap(e[de(i)],e[de(m)]); 90 end; 91 inc(i); 92 end; 93 if l=r then 94 begin 95 writeln('Yes');resume(now);exit; 96 end; 97 i:=1;j:=m; 98 while i<=j do 99 begin 100 if e[i].st>mid then swap(e[de(i)],e[de(j)]); 101 inc(i); 102 end; 103 solve(l,mid,j); 104 i:=1;j:=m; 105 while i<=j do 106 begin 107 if e[i].ed<=mid then swap(e[de(i)],e[de(j)]); 108 inc(i); 109 end; 110 solve(mid+1,r,j); 111 resume(now); 112 end; 113 114 begin 115 readln(n,m,t); 116 for i:=1 to n do 117 begin 118 fa[i]:=i;a[i]:=false;d[i]:=1; 119 end; 120 i:=1; 121 while i<=m do 122 begin 123 readln(e[i].u,e[i].v,e[i].st,e[i].ed); 124 inc(e[i].st); 125 if e[i].st>e[i].ed then 126 begin 127 dec(i);dec(m); 128 end; 129 inc(i); 130 end; 131 top:=0; 132 solve(1,t,m); 133 end.