首页 > 其他 > 详细

BZOJ 4025: 二分图

时间:2020-02-08 15:03:12      阅读:57      评论:0      收藏:0      [点我收藏+]

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

#include <bits/stdc++.h>

namespace IO {
    void read() {}
    template<class T, class... T2>
    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<int> &vec) {
    int tp = top;
    int mid = l + r >> 1;
    std::vector<int> 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<int> 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: 二分图

原文:https://www.cnblogs.com/Mrzdtz220/p/12275943.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!