• luoguP4320 道路相遇 圆方树


    标题已经告诉你怎么做了.....

    两点间的圆点个数即为所求

    建出圆方树后打个树剖求$lca$就行.....

    复杂度$O(n + q log n)$

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    using namespace std;
    
    extern inline char gc() {
        static char RR[23456], *S = RR + 23333, *T = RR + 23333;
        if(S == T) fread(RR, 1, 23333, stdin), S = RR;
        return *S ++;
    }
    inline int read() {
        int p = 0, w = 1; char c = gc();
        while(c > '9' || c < '0') { if(c == '-') w = -1; c = gc(); }
        while(c >= '0' && c <= '9') p = p * 10 + c - '0', c = gc();
        return p * w;
    }
    
    int wr[50], rw;
    #define pc(o) *O ++ = o
    char WR[40000005], *O = WR;
    inline void write(int x) {
        if(!x) pc('0');
        if(x < 0) pc('-'), x = -x;
        while(x) wr[++ rw] = x % 10, x /= 10;
        while(rw) pc(wr[rw --] + '0'); pc('
    ');
    }
    
    #define ri register int
    #define sid 500050
    #define nid 1005000
    #define eid 4005000
    
    int n, m, cnp;
    int cap[sid], aap[nid], nxt[eid], node[eid]; 
    
    inline void cop(int u, int v) { nxt[++ cnp] = cap[u]; cap[u] = cnp; node[cnp] = v; }
    inline void bop(int u, int v) { nxt[++ cnp] = aap[u]; aap[u] = cnp; node[cnp] = v; }
    
    int st[sid], snp, scc;
    int dfn[sid], low[sid], dfn_id;
    
    #define cur node[i]
    
    void tarjan(int o) {
        st[++ snp] = o;
        dfn[o] = low[o] = ++ dfn_id;
        for(int i = cap[o]; i; i = nxt[i])
        if(!dfn[cur]) {
            tarjan(cur); low[o] = min(low[o], low[cur]);
            if(low[cur] < dfn[o]) continue;
            int e; ++ scc; bop(o, scc);
            do { e = st[snp --]; bop(scc, e); } while(e != cur);
        }
        else low[o] = min(low[o], dfn[cur]);
    }
    
    int anc[nid], fa[nid], sz[nid];
    int dep[nid], de[nid], son[nid];
    
    void dfs(int o) {
        sz[o] = 1; de[o] = de[fa[o]] + (o <= n);
        for(int i = aap[o]; i; i = nxt[i])
        if(cur != fa[o]) {
            dep[cur] = dep[o] + 1; fa[cur] = o; 
            dfs(cur); sz[o] += sz[cur];
            if(sz[son[o]] < sz[cur]) son[o] = cur;
        }
    }
    
    void dfs(int o, int tp) {
        anc[o] = tp; if(!son[o]) return; dfs(son[o], tp);
        for(int i = aap[o]; i; i = nxt[i])
        if(cur != fa[o] && cur != son[o]) dfs(cur, cur);
    }
    
    int lca(int u, int v) {
        int pu = anc[u], pv = anc[v];
        while(pu != pv) {
            if(dep[pu] < dep[pv]) swap(u, v), swap(pu, pv);
            u = fa[pu]; pu = anc[u];
        } 
        return (dep[u] < dep[v]) ? u : v;
    }
    
    int main() {
        scc = n = read(); m = read();
        for(ri i = 1; i <= m; i ++) {
            int u = read(), v = read();
            cop(u, v); cop(v, u);
        }
        tarjan(1); dfs(1); dfs(1, 1);
        int q = read();
        for(ri i = 1; i <= q; i ++) {
            int u = read(), v = read(), o = lca(u, v);
            write(de[u] + de[v] - de[o] - de[fa[o]]);
        }
        fwrite(WR, 1, O - WR, stdout);
        return 0;
    }
  • 相关阅读:
    分分钟制作微信朋友圈页面
    js模板引擎原理,附自己写的简洁模板引擎
    基于H5 pushState实现无跳转页面刷新
    随手学和记——PHP快速上手基础
    ES5 特性概览
    JavaScript错误和异常
    JavaScript闭包探究
    FastDFS总结
    C++11笔记
    leveldb源码笔记
  • 原文地址:https://www.cnblogs.com/reverymoon/p/9521093.html
Copyright © 2020-2023  润新知