zoukankan      html  css  js  c++  java
  • 4025: 二分图

    4025: 二分图

    链接

    分析:

      线段树分治+并查集。

      以时间为下标建立一颗线段树,对于每条边u,v,l,r,在期出现的时间[l,r]的时间上打标记,表示时间[l,r]存在这条边,那么在线段树上递归到叶子结点,就是每个时刻所有出现的边。

      从根节点出发,把所有的边加入,并查集维护是否合法,如果到叶子结点了,依然是合法的,那么这个时刻就是可行的。

      退出一个点的时候,并查集中也要撤销的,所以不能路径压缩,可以按秩合并。

      如何判断是否合法?不存在奇环。即可以黑白染色。考虑并查集如果每个点的颜色。合并时,在并查集的根上打一个标记,如果存在这个标记,说明这个集合内的点的颜色取反。那么一个点的颜色就是从这个点出发,到根节点的路径上的异或和。

      同样可以CDQ分治,把每条线段拆成两个操作,在l出加入,在r处删除,询问T次。

    代码:

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<iostream>
    #include<cmath>
    #include<cctype>
    #include<set>
    #include<queue>
    #include<vector>
    #include<map>
    #define pa pair<int,int>
    using namespace std;
    typedef long long LL;
    
    inline int read() {
        int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
        for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
    }
    
    const int N = 200005;
    int col[N], h[N], ans[N], fa[N];
    vector< pa > e[N << 2];
    struct OPT{ int x, y, f; };
    vector<OPT> g[N << 2];
    
    void update(int l,int r,int rt,int L,int R,int u,int v) {
        if (L > r || R < l) return ;
        if (L <= l && r <= R) {
            e[rt].push_back(pa(u, v)); return ;
        }
        int mid = (l + r) >> 1;
        if (L <= mid) update(l, mid, rt << 1, L, R, u, v);
        if (R > mid) update(mid + 1, r, rt << 1 | 1, L, R, u, v);
    }
    int findcol(int &x) {
        int c = 0;
        while (x != fa[x]) c ^= col[x], x = fa[x];
        return c;
    }
    void query(int l,int r,int rt) {
        bool flag = false;
        for (int i = 0; i < (int)e[rt].size(); ++i) {
            int x = e[rt][i].first, y = e[rt][i].second;
            int a = findcol(x), b = findcol(y);
            if (x == y) {
                if (a == b) {
                    flag = true;
                    for (int j = l; j <= r;  ++j) ans[j] = false;
                    break;
                }
                continue;
            }
            if (h[x] < h[y]) swap(x, y);
            fa[y] = x, col[y] = a ^ b ^ 1;
            if (h[x] == h[y]) h[x] += 1;
            g[rt].push_back((OPT){x, y, (h[x] == h[y])});
        }
        int mid = (l + r) >> 1;
        if (!flag && l != r) query(l, mid, rt << 1), query(mid + 1, r, rt << 1 | 1);
        for (int i = g[rt].size() - 1; ~i; --i) {
            int x = g[rt][i].x, y = g[rt][i].y;
            fa[y] = y, col[y] = 0, h[x] -= g[rt][i].f;
        }
    }
    int main() {
        int n = read(), m = read(), T = read();
        for (int i = 1; i <= n; ++i) fa[i] = i, h[i] = 1;
        for (int i = 1; i <= T; ++i) ans[i] = 1;
        for (int i = 1; i <= m; ++i) {
            int u = read(), v = read(), l = read() + 1, r = read();
            if (l > r) continue; 
            update(1, T, 1, l, r, u, v);
        }
        query(1, T, 1);
        for (int i = 1; i <= T; ++i) puts(ans[i] ? "Yes" : "No");
        return 0;
    }
  • 相关阅读:
    python list dict 去重的两种方式
    python 发送邮件
    mongo 查询总结
    vsftpd 安装配置
    简单配置 nginx 反向代理
    python 检查内存
    python ldap
    Centos 7 vsftpd ldap 配置
    centos7虚拟机开启端口后 外部不能访问的问题
    Linux下安装配置rocketmq (单个Master、双Master)
  • 原文地址:https://www.cnblogs.com/mjtcn/p/10501940.html
Copyright © 2011-2022 走看看