BZOJ 4025: 二分图

线段树分治+按秩合并的并查集解决加边删边的问题。
一个图是二分图当且仅当点数大于等于二并且不存在奇环。
那么可以用带权并查集维护路径长度,会出现环就是当加入一条边是产生环并且原路径长度为偶数。

#include 

namespace IO {
    void read() {}
    template
    void read(T &x, T2 &... oth) {
        x = 0; T f = 1; char ch = getchar();
        while (!isdigit(ch)) { if (ch == '-') f = -1; ch = getchar(); }
        while (isdigit(ch)) x = x * 10 + ch - '0', ch = getchar();
        x *= f;
        read(oth...);
    }
}

const int N = 2e5 + 7;

int st[N], top;

struct DSU {
    int fa[N], d[N], dep[N];
    void init(int n) {
        for (int i = 0; i <= n; i++)
            fa[i] = i, d[i] = dep[i] = 0;
    }
    int getfa(int x) {
        while (x != fa[x]) 
            x = fa[x];
        return x;
    }
    int getdis(int x) {
        int dis = 0;
        while (x != fa[x])
            dis ^= d[x], x = fa[x];
        return dis;
    }
    bool merge(int x, int y) {
        int D = getdis(x) ^ getdis(y) ^ 1;
        x = getfa(x), y = getfa(y);
        if (x == y) return D == 0;
        if (dep[x] < dep[y]) 
            std::swap(x, y);
        if (dep[x] == dep[y])
            dep[x]++, st[++top] = -x;
        fa[y] = x; d[y] = D; st[++top] = y;
        return 1;
    }
    void del(int tp) {
        while (top > tp) {
            int x = st[top--];
            if (x < 0)
                dep[-x]--;
            else 
                fa[x] = x, d[x] = 0;
        }
    }
} dsu;

int n, m, T;
struct P {
    int u, v, x, y;
} p[N];
int ans[N];

void solve(int l, int r, const std::vector &vec) {
    int tp = top;
    int mid = l + r >> 1;
    std::vector L, R;
    for (int i = 0, sz = vec.size(); i < sz; i++) {
        int id = vec[i];
        if (p[id].x <= l && r <= p[id].y) {
            if (!dsu.merge(p[id].u, p[id].v)) {
                for (int j = l; j <= r; j++)
                    ans[j] = 1;
                dsu.del(tp);
                return;
            }
        } else {
            if (p[id].x <= mid)
                L.push_back(id);
            if (p[id].y > mid)
                R.push_back(id);
        }
    }
    if (l == r) {
        dsu.del(tp);
        return;
    }
    solve(l, mid, L);
    solve(mid + 1, r, R);
    dsu.del(tp);
}

int main() {
    IO::read(n, m, T);
    dsu.init(n);
    std::vector vec;
    for (int i = 1; i <= m; i++)
        IO::read(p[i].u, p[i].v, p[i].x, p[i].y), p[i].x++, vec.push_back(i);
    solve(1, T, vec);
    for (int i = 1; i <= T; i++)
        puts(ans[i] ? "No" : "Yes");
    return 0;
}

你可能感兴趣的:(BZOJ 4025: 二分图)