• BZOJ 4025: 二分图


    4025: 二分图
    思路:
    考虑按时间分治,然后把每条边按影响时间加入相应的区间(类似划分树)。然后考虑把包含每个叶子节点的边连起来,并判断有没有奇环。
    由于分治时需要撤回某些并查集的合并操作,所以需要用到可撤销并查集。然后因为要判基环,所以又需要维护每个点到父亲节点的距离(dp[i])
    所以需要用到带权并查集。
    代码:

    #pragma GCC optimize(2)
    #pragma GCC optimize(3)
    #pragma GCC optimize(4)
    #include<bits/stdc++.h>
    using namespace std;
    #define y1 y11
    #define fi first
    #define se second
    #define pi acos(-1.0)
    #define LL long long
    #define mp make_pair
    #define pb push_back
    #define ls rt<<1, l, m
    #define rs rt<<1|1, m+1, r
    #define ULL unsigned LL
    #define pll pair<LL, LL>
    #define pli pair<LL, int>
    #define pii pair<int, int>
    #define piii pair<pii, int>
    #define pdd pair<double, double>
    #define mem(a, b) memset(a, b, sizeof(a))
    #define debug(x) cerr << #x << " = " << x << "
    ";
    #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    //head
     
    const int N = 1e5 + 5;
    int n, m, T, u, v, l, r;
    vector<pii> vc[N<<2];
    bool ans[N];
    struct UFS {
        stack<pair<int*, int> > stk;
        int fa[N], rnk[N], dp[N], c;
        inline void init(int n) {
            for (int i = 0; i <= n; ++i) fa[i] = i, rnk[i] = 0, dp[i] = 0;
            c = 0;
        }
        inline int Find(int x) {
            while(x^fa[x]) x = fa[x];
            return x;
        }
        inline int Deep(int x) {
            int res = 0;
            while(x^fa[x]) res += dp[x], x = fa[x];
            return res;
        }
        inline void Merge(int x, int y) {
            int fx = Find(x), fy = Find(y);
            if(fx == fy) {
                int dx = Deep(x), dy = Deep(y);
                if((dx+dy+1)%2) {
                    stk.push(mp(&c, c));
                    c++;
                }
                return ;
            }
            if(rnk[fx] <= rnk[fy]) {
                stk.push(mp(fa+fx, fa[fx]));
                stk.push(mp(dp+fx, dp[fx]));
                dp[fx] = dp[y]-dp[x]+1;
                fa[fx] = fy;
                if(rnk[fx] == rnk[fy]) {
                    stk.push(mp(rnk+fy, rnk[fy]));
                    rnk[fy]++;
                }
            }
            else {
                stk.push(mp(fa+fy, fa[fy]));
                stk.push(mp(dp+fy, dp[fy]));
                dp[fy] = dp[x]-dp[y]+1;
                fa[fy] = fx;
            }
        }
        inline void Undo() {
            *stk.top().fi = stk.top().se;
            stk.pop();
        }
    }ufs;
    void update(int L, int R, pii p, int rt, int l, int r) {
        if(L <= l && r <= R) return vc[rt].pb(p), void();
        int m = (l+r) >> 1;
        if(L <= m)update(L, R, p, ls);
        if(R > m) update(L, R, p, rs);
    }
    void dfs(int rt, int l, int r) {
        for (int i = 0; i < vc[rt].size();++i) ufs.Merge(vc[rt][i].fi, vc[rt][i].se);
        if(l == r) {
            if(ufs.c) printf("No
    ");
            else printf("Yes
    ");
            return ;
        }
        int sz = ufs.stk.size();
        int m = (l+r) >> 1;
        dfs(ls);
        while(ufs.stk.size() > sz) ufs.Undo();
        dfs(rs);
        while(ufs.stk.size() > sz) ufs.Undo();
    }
    int main() {
        scanf("%d %d %d", &n, &m, &T);
        for (int i = 1; i <= m; ++i) scanf("%d %d %d %d", &u, &v, &l, &r), update(l+1, r, {u, v}, 1, 1, T);
        ufs.init(n);
        dfs(1, 1, T);
        return 0;
    }
    
  • 相关阅读:
    java矩阵运算包ujmp中的一些小示例和注意事项
    CSS文字段落排版常用设置
    HTML中标签元素的分类
    三种CSS样式-内联、嵌入、外部
    MySQL常用命令
    解决谷歌浏览器在win8下没有注册类的问题
    转:jQuery.lazyload详解使用方法
    php取整
    限制表单Input的长度,当达到一定长度时不能再输入
    滑动后定位
  • 原文地址:https://www.cnblogs.com/widsom/p/11335239.html
Copyright © 2020-2023  润新知