• 道路相遇 圆方树,树链剖分


    道路相遇

    基础圆方树。

    不会圆方树看我另一篇文章

    LG传送门

    发现必经之路上的点一定是简单路径上的点,可以自己手玩。处理无向图上的简单路径,考虑把圆方树建出来,发现答案就是圆方树上两点间圆点个数。由于广义圆方树上圆方点相间,可以用深度表示答案,发现答案就是((dep[u] + dep[v] - 2 * dep[lca]) / 2 + 1),lca树剖求。

    #include <cstdio>
    #include <cctype>
    #include <vector>
    #define R register
    #define I inline
    #define B 10000000
    using namespace std;
    const int N = 1000003;
    char buf[B], *p1, *p2;
    I char gc() { return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, B, stdin), p1 == p2) ? EOF : *p1++; }
    I int rd() {
        R int f = 0; R char c = gc();
        while (c < 48 || c > 57)
            c = gc();
        while (c > 47 && c < 58)
            f = f * 10 + (c ^ 48), c = gc();
        return f;
    }
    int s[N], S[N], vis[N], dfn[N], low[N], sta[N], fa[N], dep[N], siz[N], son[N], top[N], tim, cnt, stp;
    vector <int> g[N], G[N];
    I int min(int x, int y) { return x < y ? x : y; }
    I void swap(int &x, int &y) { x ^= y, y ^= x, x ^= y; }
    void dfs(int x) {
        vis[sta[++stp] = x] = 1, dfn[x] = low[x] = ++tim;
        for (R int i = 0, y ,z; i < s[x]; ++i)
            if (!dfn[y = g[x][i]]) {
                dfs(y), low[x] = min(low[x], low[y]);
                if (low[y] >= dfn[x]) {
                    G[++cnt].push_back(x), G[x].push_back(cnt);
                    do {
                        vis[z = sta[stp--]] = 0, G[cnt].push_back(z), G[z].push_back(cnt);
                    } while (z ^ y);
                }
            }
            else
                low[x] = min(low[x], dfn[y]);
    }
    void dfs1(int x, int f) {
        fa[x] = f, dep[x] = dep[f] + 1, siz[x] = 1;
        for (R int i = 0, y, m = 0; i < S[x]; ++i)
            if ((y = G[x][i]) ^ f) {
                dfs1(y, x), siz[x] += siz[y];
                if (siz[y] > m)
                    m = siz[y], son[x] = y;
            }
    }
    void dfs2(int x, int r) {
        top[x] = r;
        if (son[x])
            dfs2(son[x], r);
        for (R int i = 0, y; i < S[x]; ++i)
            if ((y = G[x][i]) ^ fa[x] && y ^ son[x])
                dfs2(y, y);
    }
    I int query(int x, int y) {
        R int  o = dep[x] + dep[y];
        while (top[x] ^ top[y]) {
            if (dep[top[x]] < dep[top[y]])
                swap(x, y);
            x = fa[top[x]];
        }
        if (dep[x] > dep[y])
            swap(x, y);
        return ((o - (dep[x] << 1)) >> 1) + 1;
    }
    int main() {
        R int n = rd(), m = rd(), Q, i, x, y;
        for (i = 1; i <= m; ++i)
            x = rd(), y = rd(), g[x].push_back(y), g[y].push_back(x);
        for (i = 1; i <= n; ++i)
            s[i] = g[i].size();
        Q = rd(), cnt = n, dfs(1);
        for (i = 1; i <= cnt; ++i)
            S[i] = G[i].size();
        dfs1(1, 0), dfs2(1, 1);
        for (i = 1; i <= Q; ++i)
            x = rd(), y = rd(), printf("%d
    ", query(x, y));
        return 0;
    }
    
    
  • 相关阅读:
    LSTM模型与前向反向传播算法
    循环神经网络(RNN)模型与前向反向传播算法
    卷积神经网络(CNN)反向传播算法
    卷积神经网络(CNN)前向传播算法
    卷积神经网络(CNN)模型结构
    深度神经网络(DNN)的正则化
    深度神经网络(DNN)损失函数和激活函数的选择
    ubuntu下如何编译openthread?
    linux下如何删除空行?
    vi下什么快捷键可以完成大小写转换?
  • 原文地址:https://www.cnblogs.com/cj-chd/p/10293730.html
Copyright © 2020-2023  润新知