zoukankan      html  css  js  c++  java
  • Codeforces 97E Leaders 点双联通

    Leaders

    我们随便找一颗生成树出来, 如果询问的两点的距离为奇数则肯定可以, 

    否则看两点树上路径中有没有边在一个奇环中, 对于一个点双联通分量来说,

    要么没有奇环, 要么两两之间都有奇环, 这个画画图就能知道,

    然后求个bcc的过程中处理一下就好了。

    #include<bits/stdc++.h>
    #define fi first
    #define se second
    #define mk make_pair
    #define PII pair<int, int>
    using namespace std;
    
    const int N = (int)1e5 + 7;
    const int LOG = 17;
    
    int n, m, q;
    int depth[N], pa[N][LOG], val[N];
    bool odd[N], vis[N];
    vector<PII> G[N];
    
    int col[N], col_cnt;
    int dfn[N], low[N], dfs_clock;
    
    struct Edge {
        int u, v, id;
    };
    
    vector<Edge> E;
    Edge estk[N];
    int etop;
    
    int fa[N], w[N];
    
    int getRoot(int x) {
        if(fa[x] == x) return x;
        int rt = getRoot(fa[x]);
        w[x] ^= w[fa[x]];
        return fa[x] = rt;
    }
    
    bool unite(int u, int v) {
        int x = getRoot(u);
        int y = getRoot(v);
        if(x == y) {
            return !(w[u] ^ w[v] ^ 1);
        }
        else {
            w[y] = w[u] ^ w[v] ^ 1;
            fa[y] = x;
            return true;
        }
    }
    
    void tarjan(int u, int eid) {
        dfn[u] = low[u] = ++dfs_clock;
        col[u] = col_cnt;
        for(int i = 0; i < G[u].size(); i++) {
            int v = G[u][i].se, id = G[u][i].fi;
            if(id == eid) continue;
            if(!dfn[v]) {
                estk[++etop] = Edge{u, v, id};
                tarjan(v, id);
                low[u] = min(low[u], low[v]);
                if(low[v] >= dfn[u]) {
                    E.clear();
                    while(1) {
                        E.push_back(estk[etop--]);
                        if(E.back().id == id) break;
                    }
                    for(auto &e : E) {
                        fa[e.u] = e.u;
                        fa[e.v] = e.v;
                        w[e.u] = w[e.v] = 0;
                    }
                    bool flag = true;
                    for(auto &e : E) {
                        if(!unite(e.u, e.v)) {
                            flag = false;
                            break;
                        }
                    }
                    if(!flag) {
                        for(auto &e : E) {
                            odd[e.id] = true;
                        }
                    }
                }
            }
            else if(dfn[v] < dfn[u]) {
                estk[++etop] = Edge{u, v, id};
                low[u] = min(low[u], dfn[v]);
            }
        }
    }
    
    
    void dfs(int u, int fa) {
        vis[u] = true;
        depth[u] = depth[fa] + 1;
        pa[u][0] = fa;
        for(int i = 1; i < LOG; i++) {
            pa[u][i] = pa[pa[u][i - 1]][i - 1];
        }
        for(int i = 0; i < G[u].size(); i++) {
            int v = G[u][i].se, id = G[u][i].fi;
            if(vis[v]) continue;
            val[v] = val[u] + odd[id];
            dfs(v, u);
        }
    }
    
    int getLca(int u, int v) {
        if(depth[u] < depth[v]) swap(u, v);
        int d = depth[u] - depth[v];
        for(int i = LOG - 1; i >= 0; i--) {
            if(d >> i & 1) {
                u = pa[u][i];
            }
        }
        if(u == v) return u;
        for(int i = LOG - 1; i >= 0; i--) {
            if(pa[u][i] != pa[v][i]) {
                u = pa[u][i];
                v = pa[v][i];
            }
        }
        return pa[u][0];
    }
    
    inline int getDis(int u, int v) {
        int lca = getLca(u, v);
        return depth[u] + depth[v] - 2 * depth[lca];
    }
    inline int getVal(int u, int v) {
        int lca = getLca(u, v);
        return val[u] + val[v] - 2 * val[lca];
    }
    
    int main() {
        scanf("%d%d", &n, &m);
        for(int i = 1; i <= m; i++) {
            int u, v;
            scanf("%d%d", &u, &v);
            G[u].push_back(mk(i, v));
            G[v].push_back(mk(i, u));
        }
        for(int i = 1; i <= n; i++) {
            if(!dfn[i]) {
                col_cnt++;
                tarjan(i, 0);
            }
        }
        for(int i = 1; i <= n; i++) {
            if(!vis[i]) {
                dfs(i, 0);
            }
        }
        scanf("%d", &q);
        while(q--) {
            int u, v;
            scanf("%d%d", &u, &v);
            if(col[u] != col[v] || !getVal(u, v) && !(getDis(u, v) & 1)) puts("No");
            else puts("Yes");
        }
        return 0;
    }
    
    /*
    */
  • 相关阅读:
    Windows Server 2012配置开机启动项
    Windows Server 2019 SSH Server
    NOIP2017 senior A 模拟赛 7.7 T1 棋盘
    Noip 2015 senior 复赛 Day2 子串
    Noip 2015 senior复赛 题解
    Noip 2014 senior Day2 解方程(equation)
    Noip 2014 senior Day2 寻找道路(road)
    Noip 2014 senior Day2 无线网络发射器选址(wireless)
    Noip2014senior复赛 飞扬的小鸟
    Noip 2014 senior 复赛 联合权值(link)
  • 原文地址:https://www.cnblogs.com/CJLHY/p/11610656.html
Copyright © 2011-2022 走看看