萌新求助边双+树剖求LCA
查看原帖
萌新求助边双+树剖求LCA
158846
xixike楼主2021/11/16 22:54

rt,WA 了后三个点,求大佬们帮帮看看。

重边也判了不过不知道判的对不对,用maphash了一下判的。

#include <bits/stdc++.h>

using namespace std;

namespace IO{
    inline int read(){
        int x = 0;
        char ch = getchar();
        while(!isdigit(ch)) ch = getchar();
        while(isdigit(ch)) x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
        return x;
    }

    template <typename T> inline void write(T x){
        if(x > 1) write(x / 2);
        putchar(x % 2 + '0');
    }
}
using namespace IO;

const int N = 1e5 + 1;//根据题解,怒开10倍数组,然然还是WA QAQ
const int M = 5e5 + 1;
unordered_map <int, bool> mp;
int n, m, q;
struct node{
    int u, v, nxt;
}edge[M << 1];
int head[N], tot = 1;
int bri[N << 1];

inline void add(int x, int y){
    edge[++tot] = (node){x, y, head[x]};
    head[x] = tot;
}

namespace Tarjan{
    int dfn[N], low[N], tim;
    int stk[N], top;
    bool vis[N];
    int cnt, scc[N];
    queue <int> que;

    inline void tarjan(int x, int e){
        dfn[x] = low[x] = ++tim;
        for(int i = head[x]; i; i = edge[i].nxt){
            int y = edge[i].v;
            if(e == (i ^ 1)) continue;
            if(!dfn[y]){
                tarjan(y, i), low[x] = min(low[x], low[y]);
                if(low[y] > dfn[x]) bri[i] = bri[i ^ 1] = 1;
            }else low[x] = min(low[x], dfn[y]);
        }
    }

    inline void dfs(int x){
        vis[x] = 1;
        que.push(x);
        for(int i = head[x]; i; i = edge[i].nxt){
            int y = edge[i].v;
            if(!vis[y] && !bri[i]) dfs(y);
        }
    }
}
using namespace Tarjan;

namespace Cut_Tree{
    int siz[N], son[N], fa[N], dep[N];
    int top[N], dfn[N], tim;
    vector <int> g[N];

    inline void dfs1(int x, int p){
        fa[x] = p, dep[x] = dep[p] + 1, siz[x] = 1;
        for(auto y : g[x]){
            if(y == p) continue;
            dfs1(y, x);
            siz[x] += siz[y];
            if(siz[y] > siz[son[x]]) son[x] = y;
        }
    }

    inline void dfs2(int x, int topfa){
        dfn[x] = ++tim, top[x] = topfa;
        if(!son[x]) return;
        dfs2(son[x], topfa);
        for(auto y : g[x]){
            if(y == fa[x] || y == son[x]) continue;
            dfs2(y, y);
        }
    }

    inline int lca(int x, int y){
        while(top[x] != top[y]){
            if(dep[top[x]] < dep[top[y]]) swap(x, y);
            x = fa[top[x]];
        }
        return dep[x] < dep[y] ? x : y;
    }
}
using namespace Cut_Tree;

int main(){
    n = read(), m = read();
    for(int i = 1; i <= m; ++i){
        int u = read(), v = read();
        if(u > v) swap(u, v);
        if(!mp[u * n + v]) add(u, v), add(v, u), mp[u * n + v] = 1;//判重边,不知道这样写对不对 QwQ
    }
    for(int i = 1; i <= n; ++i)//找桥
        if(!Tarjan::dfn[i]) tarjan(i, 1);
    for(int i = 1; i <= n; ++i){//找到所有联通块
        if(!vis[i]){
            dfs(i), cnt++;
            while(!que.empty())
                scc[que.front()] = cnt, que.pop();
        }
    }
	mp.clear();
    for(int i = 2; i <= tot; ++i){//建新树
        int u = scc[edge[i].u], v = scc[edge[i].v];
		if(u > v) swap(u, v);
		if(u != v && !mp[u * n + v]){
			g[u].push_back(v), g[v].push_back(u);
			mp[u * n + v] = 1;
		}
    }
    dfs1(1, 0), dfs2(1, 1);
    q = read();
    while(q--){
        int x = read(), y = read();
        write(dep[x] + dep[y] - (dep[lca(x, y)] << 1) + 1), puts("");
    }
    return 0;
}
2021/11/16 22:54
加载中...