BZOJ 4025 [并查集][二分图][分治]

来源:互联网 发布:流程优化的方法 编辑:程序博客网 时间:2024/06/05 02:24

Description

有一张n个点m条边的图,第i条边在Si时刻出现,Ti时刻消失,对于1~T的每个时刻,判断图是不是二分图。

Solution

其实就是看每个时刻存不存在奇环。
可以分治+LCT
可以直接LCT
可以分治+带权并查集(按秩合并后可以暴力爬树高也可以暴力撤回边都是O(logn)的)

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#include <vector>using namespace std;inline char get(void) {    static char buf[100000], *S = buf, *T = buf;    if (S == T) {        T = (S = buf) + fread(buf, 1, 100000, stdin);        if (S == T) return EOF;    }    return *S++;}inline void read(int &x) {    static char c; x = 0;    for (c = get(); c < '0' || c > '9'; c = get());    for (; c >= '0' && c <= '9'; c = get()) x = x * 10 + c - '0';}const int N = 101010;const int M = 202020;int n, m, T;int ans[N];struct Qry {    int L, R, u, v;    inline friend bool operator <(const Qry &a, const Qry &b) {        return a.L == b.L ? a.R < b.R : a.L < b.L;    }};Qry Q[M];vector<Qry> V;namespace dsu {    int rk[N], fa[N], dis[N];    int sta[N << 2], drk[N << 2];    int top;    inline int Fa(int x) {        while (fa[x] != x) x = fa[x];        return x;    }    inline int Union(int x, int y, int d) {        static int f1, f2;        f1 = Fa(x); f2 = Fa(y);        if (f1 == f2) return 0;        top++;        if (rk[f1] > rk[f2]) swap(f1, f2);        if (rk[f1] == rk[f2]) rk[f2]++, drk[top] = 1;        fa[f1] = f2; dis[f1] = d; sta[top] = f1;        return 1;    }    inline int Dis(int x) {        int dep = 0;        while (fa[x] != x) dep ^= dis[x], x = fa[x];        return dep;    }    inline void Reset(int pos) {        for (; top > pos; top--) {            rk[fa[sta[top]]] -= drk[top];            fa[sta[top]] = sta[top];            dis[sta[top]] = 0;        }    }};using namespace dsu;void DivAndConq(int l, int r, vector<Qry> &V) {    int mid = (l + r) >> 1, now = top, D;    vector<Qry> L, R;    for (int i = 0; i < V.size(); i++) {        Qry o = V[i];        if (o.L == l && o.R == r) {            int x = o.u, y = o.v;            D = Dis(x) ^ Dis(y) ^ 1;            if ((!Union(x, y, D)) && (D & 1)) return Reset(now);        }        else if (o.R <= mid) L.push_back(o);        else if (o.L > mid) R.push_back(o);        else {            o.R = mid; L.push_back(o);            o = V[i]; o.L = mid + 1;            R.push_back(o);        }    }       if (l == r) ans[l] = 1;    else {        DivAndConq(l, mid, L);        DivAndConq(mid + 1, r, R);    }    Reset(now);}int main(void) {    read(n); read(m); read(T);    for (int i = 1; i <= m; i++) {        read(Q[i].u); read(Q[i].v);        read(Q[i].L); read(Q[i].R);        Q[i].L++; if (Q[i].L <= Q[i].R) V.push_back(Q[i]);    }    sort(V.begin(), V.end());    for (int i = 1; i <= n; i++) fa[i] = i;    DivAndConq(1, T, V);    for (int i = 1; i <= T; i++)        if (ans[i]) puts("Yes");        else puts("No");    return 0;}
原创粉丝点击