道路相遇 圆方树

Posted newbiechd的博客

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了道路相遇 圆方树相关的知识,希望对你有一定的参考价值。

道路相遇

基础圆方树。

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

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\\n", query(x, y));
    return 0;
}

以上是关于道路相遇 圆方树的主要内容,如果未能解决你的问题,请参考以下文章

luogu4320道路相遇 (圆方树 + LCA)

P4320 道路相遇 (圆方树+LCA)

仙人掌&圆方树

[SDOI2018]战略游戏 圆方树,树链剖分

[圆方树] Luogu P4630 Duathlon 铁人两项

圆方树小结