• 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;
    }
    
    /*
    */
  • 相关阅读:
    javascript中的复制
    使用tensorflow-serving部署tensorflow模型
    Linux端口命令
    intellij idea强制更新索引
    The minimum required Cuda capability is 3.7.
    tensorflow没有代码提示的问题
    何为学术能力
    PageRank算法
    keras的训练引擎:train_array.py和train_generator.py
    如何阅读源代码
  • 原文地址:https://www.cnblogs.com/CJLHY/p/11610656.html
Copyright © 2020-2023  润新知