[洛谷P4320]道路相遇

题目大意:基本同上一题[bzoj5329][Sdoi2018]战略游戏,只是每个点集内只有两个点,且只有一组询问而已。(双倍经验?我反正就直接改了一下代码就交了)

题解:同上一题(链接见“题目大意”)

卡点:

 

C++ Code:

#include <cstdio>
#include <cstring>
#define maxn 1000010
#define maxm 1000010
int Tim, n, m, LCA;
inline int min(int a, int b) {return a < b ? a : b;}
inline void swap(int &a, int &b) {a ^= b ^= a ^= b;}
struct Tree {
    #define root 1
    #define fa(u) dad[u][0]
    #define M 18
    int head[maxn], cnt;
    struct Edge {
        int to, nxt;
    } e[maxm << 1];
    inline void addE(int a, int b) {e[++cnt] = (Edge) {b, head[a]}; head[a] = cnt;}
    inline void add(int a, int b) {
        addE(a, b);
        addE(b, a);
    }
    
    int dad[maxn][M], dep[maxn], sz[maxn];
    int dfn[maxn], idx;
    void dfs(int u = root) {
        dfn[u] = ++idx;
        for (int i = 1; i < M; i++) dad[u][i] = dad[dad[u][i - 1]][i - 1];
        for (int i = head[u]; i; i = e[i].nxt) {
            int v = e[i].to;
            if (v != fa(u)) {
                sz[v] = sz[u] + int(v <= n);
//				printf("link %d %d\n", v, sz[v]);
                dep[v] = dep[u] + 1;
                fa(v) = u;
                dfs(v);
            }
        }
    }
    inline int LCA(int x, int y) {
        if (dep[x] < dep[y]) swap(x, y);
        for (int i = dep[x] - dep[y]; i; i &= i - 1) x = dad[x][__builtin_ctz(i)];
        if (x == y) return x;
        for (int i = M - 1; ~i; i--) if (dad[x][i] != dad[y][i]) x = dad[x][i], y = dad[y][i];
        return fa(x);
    }
    
    inline int len(int x, int y) {
        return sz[x] + sz[y] - (sz[::LCA = LCA(x, y)] << 1);
    }
    
    inline void init() {
        memset(head, 0, sizeof head); cnt = 0;
        memset(dfn, 0, sizeof dfn); idx = 0;
        sz[root] = 0;
    }
    #undef root
    #undef fa
    #undef M
} T;

struct Graph {
    #define root 1
    int head[maxn], cnt;
    struct Edge {
        int to, nxt;
    } e[maxm << 1];
    inline void addE(int a, int b) {e[++cnt] = (Edge) {b, head[a]}; head[a] = cnt;}
    inline void add(int a, int b) {
        addE(a, b);
        addE(b, a);
    }
    
    int DFN[maxn], low[maxn], idx, CNT;
    int S[maxn], top, tmp;
    void tarjan(int u = root) {
        DFN[u] = low[u] = ++idx;
        S[++top] = u;
        for (int i = head[u]; i; i = e[i].nxt) {
            int v = e[i].to;
            if (!DFN[v]) {
                tarjan(v);
                low[u] = min(low[u], low[v]);
                if (low[v] >= DFN[u]) {
                    CNT++;
                    T.add(CNT, u);
                    do {
                        T.add(CNT, tmp = S[top--]);
                    } while (tmp != v);
                }
            } else low[u] = min(low[u], DFN[v]);
        }
    }
    
    inline void init(int n) {
        memset(head, 0, sizeof head); cnt = 0;
        memset(DFN, 0, sizeof DFN); idx = 0;
        CNT = n;
    }
    #undef root
} G;


#define OnlineJudge
#define read() R::READ()
#include <cctype>
namespace R {
    int x;
    #ifdef Online_Judge
    char *ch, op[1 << 26];
    inline void init() {
        fread(ch = op, 1, 1 << 26, stdin);
    }
    inline int READ() {
        while (isspace(*ch)) ch++;
        for (x = *ch & 15, ch++; isdigit(*ch); ch++) x = x * 10 + (*ch & 15);
        return x;
    }
    #else
    char ch;
    inline int READ() {
        ch = getchar();
        while (isspace(ch)) ch = getchar();
        for (x = ch & 15, ch = getchar(); isdigit(ch); ch = getchar()) x = x * 10 + (ch & 15);
        return x;
    }
    #endif
}

int main() {
    #ifdef Online_Judge
    R::init();
    #endif
    G.init(n = read()), T.init();
    for (int i = m = read(); i; i--) G.add(read(), read());
    G.tarjan();
    T.dfs();
    int Q = read();
    while (Q --> 0) printf("%d\n", T.len(read(), read()) + int(LCA <= n));
    return 0;
}

 

posted @ 2018-09-15 16:56  Memory_of_winter  阅读(247)  评论(0编辑  收藏  举报