BZOJ 4025: 二分图
4025: 二分图
Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 870 Solved: 333
[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
CDQ分治 + 可回溯的并查集
1 #include <bits/stdc++.h> 2 const int siz = 2000005; 3 int n, m, tim, fa[siz], sz[siz], bk[siz], tot, ans[siz]; 4 struct edge { int x, y, s, t; }e[siz]; 5 inline bool cmp1(const edge &a, const edge &b) { 6 return a.s == b.s ? a.t < b.t : a.s < b.s; 7 } inline bool cmp2(const edge &a, const edge &b) { 8 return a.t == b.t ? a.s < b.s : a.t < b.t; 9 } inline int find(int u) { 10 while (fa[u] != u)u = fa[u]; return u; 11 } inline void add(int a, int b) { 12 int A = find(a), B = find(b); 13 if (sz[A] > sz[B])fa[B] = A, sz[A] += sz[B], bk[++tot] = B; 14 else fa[A] = B, sz[B] += sz[A], bk[++tot] = A; 15 } inline bool adde(int a, int b) { 16 --a, --b; add(a << 1, b << 1 | 1), add(a << 1 | 1, b << 1); return find(a << 1) == find(a << 1 | 1); 17 } inline void rec(int a) { 18 sz[fa[a]] -= sz[a]; fa[a] = a; 19 } void solve(int L, int R, int l, int r) { 20 for (int i = l; i <= r; ++i)if (e[i].s <= L && e[i].t >= R) { if (adde(e[i].x, e[i].y)) { 21 for (int j = L; j <= R; ++j)ans[j] = 1; return; } else std::swap(e[i--], e[r--]); } 22 if (L == R)return; int top = tot, mid = (L + R) >> 1; 23 { std::sort(e + l, e + r + 1, cmp1); int t = l; while (t <= r && e[t].s <= mid)++t; solve(L, mid, l, t - 1); while (tot > top)rec(bk[tot--]); } 24 { std::sort(e + l, e + r + 1, cmp2); int t = r; while (t >= l && e[t].t >= mid + 1)--t; solve(mid + 1, R, t + 1, r); while (tot > top)rec(bk[tot--]); } 25 } signed main(void) { 26 scanf("%d%d%d", &n, &m, &tim); 27 for (int i = 1; i <= 2 * n; ++i)fa[i] = i, sz[i] = 1; 28 for (int i = 1; i <= m; ++i)scanf("%d%d%d%d", &e[i].x, &e[i].y, &e[i].s, &e[i].t), ++e[i].s; 29 solve(1, tim, 1, m); for (int i = 1; i <= tim; ++i)puts(ans[i] ? "No" : "Yes"); 30 }
@Author: YouSiki