bzoj 4025 二分图 lct
题解:
首先关于二分图的性质, 就是没有奇环边。 题目其实就是让你判断每个时段之内有没有奇环。
其次 lct 只能维护树,(反正对于我这种菜鸟选手只会维护树), 那么对于一棵树来说, 填上一条边会形成奇数环,或者偶数环。
现在我们考虑偶数环, 对于偶数环来说, 如果加上一条边都能使得这个图出现一个奇数环, 我们现在任意删除一条边,都还是会存在一个奇数环。
那么当出现偶数环的情况下, 我们可以删除一条边, 保存树的性质。
当出现奇数环的时候, 我们也需要删除某一条边, 并且需要标记被树上删除的那个边是什么边,直到那个边消失之前, 这个图就存在奇数环。
我们现在按照边的消失的时间从小到大删除边。 因为找替换边太麻烦了, 不好处理。 我们按照消失的时间处理之后, 就一定不会存在替换的边。
删除的时候, 也要顺带删除掉标记。
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define Fopen freopen("2.in","r",stdin); freopen("_out.txt","w",stdout); 4 #define LL long long 5 #define ULL unsigned LL 6 #define fi first 7 #define se second 8 #define pb push_back 9 #define lson l,m,rt<<1 10 #define rson m+1,r,rt<<1|1 11 #define lch(x) tr[x].son[0] 12 #define rch(x) tr[x].son[1] 13 #define max3(a,b,c) max(a,max(b,c)) 14 #define min3(a,b,c) min(a,min(b,c)) 15 typedef pair<int,int> pll; 16 const int inf = 0x3f3f3f3f; 17 const LL INF = 0x3f3f3f3f3f3f3f3f; 18 const LL mod = (int)1e9+7; 19 const int N = 5e5 + 100; 20 struct Node{ 21 int rev, rt, sz; 22 int son[2], pre; 23 int t, tt, id; 24 void init(){ 25 sz = rt = 1; rev = pre = son[0] = son[1] = 0; 26 tt = t = inf; 27 } 28 }tr[N]; 29 void Push_Rev(int x){ 30 if(!x) return ; 31 swap(lch(x), rch(x)); 32 tr[x].rev ^= 1; 33 } 34 void Push_Up(int x){ 35 if(!x) return ; 36 tr[x].sz = tr[lch(x)].sz + tr[rch(x)].sz + 1; 37 tr[x].id = x; 38 tr[x].tt = tr[x].t; 39 if(tr[x].tt > tr[lch(x)].tt) tr[x].id = tr[lch(x)].id, tr[x].tt = tr[lch(x)].tt; 40 if(tr[x].tt > tr[rch(x)].tt) tr[x].id = tr[rch(x)].id, tr[x].tt = tr[rch(x)].tt; 41 } 42 void Push_Down(int x){ 43 if(tr[x].rev){ 44 tr[x].rev = 0; 45 Push_Rev(lch(x)); 46 Push_Rev(rch(x)); 47 } 48 } 49 void Rev(int x){ 50 if(!tr[x].rt) Rev(tr[x].pre); 51 Push_Down(x); 52 } 53 void rotate(int x){ 54 if(tr[x].rt) return; 55 int y = tr[x].pre, z = tr[y].pre; 56 int k = (rch(y) == x); 57 tr[y].son[k] = tr[x].son[k^1]; 58 tr[tr[y].son[k]].pre = y; 59 tr[x].son[k^1] = y; 60 tr[y].pre = x; 61 tr[x].pre = z; 62 if(tr[y].rt) tr[y].rt = 0, tr[x].rt = 1; 63 else tr[z].son[rch(z) == y] = x; 64 Push_Up(y); 65 } 66 void Splay(int x){ 67 Rev(x); 68 while(!tr[x].rt){ 69 int y = tr[x].pre, z = tr[y].pre; 70 if(!tr[y].rt){ 71 if(( x == rch(y) ) != (y == rch(z))) rotate(y); 72 else rotate(x); 73 } 74 rotate(x); 75 } 76 Push_Up(x); 77 } 78 void Access(int x){ 79 int y = 0; 80 do{ 81 Splay(x); 82 tr[rch(x)].rt = 1; 83 rch(x) = y; 84 tr[y].rt = 0; 85 Push_Up(x); 86 y = x; 87 x = tr[x].pre; 88 }while(x); 89 } 90 void Make_rt(int x){ 91 Access(x); 92 Splay(x); 93 Push_Rev(x); 94 } 95 void link(int u, int v){ 96 Make_rt(u); 97 tr[u].pre = v; 98 } 99 void cut(int u, int v){ 100 Make_rt(u); 101 Access(v); 102 Splay(v); 103 tr[lch(v)].pre = 0; 104 tr[lch(v)].rt = 1; 105 tr[v].pre = 0; 106 lch(v) = 0; 107 } 108 bool judge(int u, int v){ 109 while(tr[u].pre) u = tr[u].pre; 110 while(tr[v].pre) v = tr[v].pre; 111 return u == v; 112 } 113 int n, m, u, v, st, ed, T, id, odd, t; 114 int tot; 115 int vis[N], in[N]; 116 struct node{ 117 int u, v, id, t, t2; 118 bool operator < (const node & x) const { 119 if(t != x.t) return t < x.t; 120 return t2 < x.t2; 121 } 122 }A[N]; 123 void add(int u, int v, int id, int t, int t2){ 124 ++tot; 125 A[tot].u = u; A[tot].v = v; A[tot].id = id; 126 A[tot].t = t; A[tot].t2 = t2; 127 } 128 int main(){ 129 tr[0].tt = tr[0].t = inf; 130 scanf("%d%d%d", &n, &m, &T); 131 for(int i = 1; i <= n+m; i++) 132 tr[i].init(); 133 for(int i = 1; i <= m; i++){ 134 scanf("%d%d%d%d", &u, &v, &st, &ed); 135 tr[i+n].t = ed; 136 if(st == ed) continue; 137 add(u, v, n+i, st, ed); 138 add(u, v, n+i, ed, -1); 139 } 140 sort(A+1, A+1+tot); 141 int j = 1; 142 for(int i = 0; i < T; i++){ 143 while(j <= tot && A[j].t == i){ 144 u = A[j].u, v = A[j].v, id = A[j].id, t = A[j].t2; 145 if(t == -1){ 146 if(in[id]){ 147 cut(u, id); 148 cut(v, id); 149 } 150 odd -= vis[id]; 151 } 152 else { 153 if(u == v) { 154 vis[id] = 1; 155 odd++; 156 } 157 else { 158 if(!judge(u, v)){ 159 link(u, id); 160 link(v, id); 161 in[id] = 1; 162 163 } 164 else { 165 Make_rt(u); 166 Access(v); 167 Splay(v); 168 int sz = tr[v].sz / 2; 169 int p = tr[v].id; 170 int tt = tr[v].tt; 171 if(tt >= t){ 172 if(sz%2 == 0){ 173 odd++; 174 vis[id] = 1; 175 } 176 } 177 else { 178 if(sz%2 == 0){ 179 odd++; 180 vis[p] = 1; 181 } 182 cut(u, p); 183 cut(v, p); 184 in[p] = 0; 185 link(u, id); 186 link(v, id); 187 in[id] = 1; 188 } 189 } 190 } 191 192 } 193 j++; 194 } 195 if(odd) puts("No"); 196 else puts("Yes"); 197 } 198 return 0; 199 }