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;
    }
    
    /*
    */
  • 相关阅读:
    Java实现 LeetCode 833 字符串中的查找与替换(暴力模拟)
    Java实现 LeetCode 833 字符串中的查找与替换(暴力模拟)
    Java实现 LeetCode 833 字符串中的查找与替换(暴力模拟)
    Java实现 LeetCode 832 翻转图像(位运算)
    Java实现 LeetCode 832 翻转图像(位运算)
    Java实现 LeetCode 832 翻转图像(位运算)
    Java实现 LeetCode 831 隐藏个人信息(暴力)
    Java实现 LeetCode 831 隐藏个人信息(暴力)
    Java实现 LeetCode 831 隐藏个人信息(暴力)
    how to use automapper in c#, from cf~
  • 原文地址:https://www.cnblogs.com/CJLHY/p/11610656.html
Copyright © 2011-2022 走看看