zoukankan      html  css  js  c++  java
  • bzoj4025 二分图

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=4025

    【题解】

    考虑对时间分治,用可撤回的启发式合并并查集来维护连通性。

    二分图的条件是没有奇环,用并查集判即可。

    对于时间区间[l,r],如果边在这期间都存在,那么就加入并查集,对于剩下的边分类,并且分治下去做。

    对于每条边,在log个区间表示出来了,需要进行判断,启发式合并的getf是log的,所以复杂度为O(nlog^2n)

    # include <stdio.h>
    # include <string.h>
    # include <iostream>
    # include <algorithm>
    // # include <bits/stdc++.h>
    
    using namespace std;
    
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    const int M = 5e5 + 10, N = 1e6 + 10;
    const int mod = 1e9+7;
    
    # define RG register
    # define ST static
    
    int n, m, T;
    
    struct edge {
        int u, v, st, ed;
        edge() {}
        edge(int u, int v, int st, int ed) : u(u), v(v), st(st), ed(ed) {}
    }e[M]; 
    
    int st[N];
    int stn = 0; 
    
    struct us {
        int n, fa[M], rk[M], dis[M];
        inline void set(int _n) {
             n = _n;
             for (int i=1; i<=n; ++i) fa[i] = i, rk[i] = 1, dis[i] = 0;
        }
        inline int getf(int x) {
            return fa[x] == x ? x : getf(fa[x]); 
        }
        inline int getdis(int x) {
            int d = 0;
            while(fa[x] != x) d += dis[x], x = fa[x]; 
            return d;
        }
        inline void un(int fu, int fv, int d) {
            if(rk[fu] > rk[fv]) swap(fu, fv);
            if(rk[fu] == rk[fv]) rk[fv] ++, st[++stn] = -fv; 
            fa[fu] = fv;
            dis[fu] = d; 
            ++stn;
            st[stn] = fu;
        }
        inline void re() {
            int x = st[stn]; --stn;
            if(x < 0) --rk[-x];
            else dis[x] = 0, fa[x] = x;
        }
    }E;
            
    bool ans[M]; 
    
    inline void solve(int tl, int tr, int er) {
    //    printf("l = %d, r = %d
    ", tl, tr); 
        int cur_stn = stn;
        for (int i=1; i<=er; ++i) {
            if(!(e[i].st <= tl && tr <= e[i].ed)) continue; 
    //        printf("doing: (%d, %d, %d, %d)
    ", e[i].u, e[i].v, e[i].st, e[i].ed); 
            int fu = E.getf(e[i].u), fv = E.getf(e[i].v);
            int du = E.getdis(e[i].u), dv = E.getdis(e[i].v);
            if(fu != fv) E.un(fu, fv, du+dv+1);
            else {
    //            printf("%d %d fa = %d %d %d
    ", e[i].u, e[i].v, E.fa[1], du, dv); 
                if((du+dv+1)&1) {
    //                puts("Proves odd"); 
                    while(stn != cur_stn) E.re();
                    return ;
                }
            }
            swap(e[i], e[er]); --er; --i; 
        }
        if(tl == tr) {
            ans[tl] = 1;
            while(stn != cur_stn) E.re(); 
            return ;
        }
        int mid = tl+tr >> 1;
        int ER = er;
        for (int i=1; i<=er; ++i) 
            if(e[i].st > mid) {
                swap(e[i], e[er]); 
                --er; --i;
            }
        solve(tl, mid, er);
        er = ER;
        for (int i=1; i<=er; ++i) {
            if(e[i].ed <= mid) {
                swap(e[i], e[er]);
                --er; --i;
            }
        }
        solve(mid+1, tr, er); 
        while(stn != cur_stn) E.re(); 
    }
    
    int main() {
        cin >> n >> m >> T;
        E.set(n); 
        int en = 0;
        for (int i=1, u, v, sta, end; i<=m; ++i) {
            scanf("%d%d%d%d", &u, &v, &sta, &end);
            ++sta; if(sta>end) continue;
            e[++en] = edge(u, v, sta, end);
        }
        m = en;
        solve(1, T, m); 
        for (int i=1; i<=T; ++i) puts(ans[i] ? "Yes" : "No"); 
        return 0;
    }
    View Code
  • 相关阅读:
    cookie和session的区别
    使用Flexible实现手淘H5页面的终端适配
    跟自己说::::
    前端稀奇古怪的问题!!!
    为什么我老是能碰见那些糟心的事?
    谈谈我的工作日常;
    毕业后,女生要到美国发展;
    工作常识总结
    git用法
    1.date对象
  • 原文地址:https://www.cnblogs.com/galaxies/p/bzoj4025.html
Copyright © 2011-2022 走看看