CF1045C Hyperspace Highways(园方树)

观察到所有成环的之间的距离都是1,因此可以想到使用tarjan缩点后建立园方树

这样答案就是两点间距离/2

#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> pll;
const int N=1e6+10;
int h[N],e[N],ne[N],idx;
int dfn[N],ins[N],low[N],w[N],times;
int depth[N],fa[N],ans[N][25],fa_e[N];
int vcc[N];
stack<int> st,st_e;
vector<int> g[N];
int cnt;
int n,m,q;
void add(int a,int b){
    e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
void dfs(int u){
    ins[u]=1;
    dfn[u]=low[u]=++times;
    int i;
    st.push(u);
    for(int i=h[u];i!=-1;i=ne[i]){
        int v=e[i];
        if(!dfn[v]){
            fa[v]=u;
            dfs(v);
            low[u]=min(low[u], low[v]);
            if(dfn[u]<=low[v]){
                ++cnt;
                while(1){
                    auto x=st.top();
                    g[cnt].push_back(x);
                    g[x].push_back(cnt);
                    ins[x]=0; st.pop();
                    if(x == v) break;
                }
                g[cnt].push_back(u);
                g[u].push_back(cnt);
            }
        }
        else if(v!=fa[u]){
            low[u]=min(low[u], dfn[v]);
        }
    }
}
int vis[N];
void dfs2(int u){
    vis[u]=1;
    for(int j=1;j<=20;j++){
        if(depth[u] <= (1<<j))
            break;
        ans[u][j] = ans[ans[u][j-1]][j-1];
    }
    int v;
    for(int k=0;k<g[u].size();k++){
        v=g[u][k];
        if(vis[v])
            continue;
        ans[v][0]=u;
        depth[v]=depth[u]+1;
        dfs2(v);
    }
}
int lca(int a,int b){
    if(depth[a]<depth[b])
    swap(a,b);
    int i;
    for(i=20;i>=0;i--){
        if(depth[ans[a][i]]>=depth[b]){
            a=ans[a][i];
        }
    }
    if(a==b)
    return a;
    for(i=20;i>=0;i--){
        if(ans[a][i]!=ans[b][i]){
            a=ans[a][i];
            b=ans[b][i];
        }
    }
    return ans[a][0];
}
int main(){
    ios::sync_with_stdio(false);
    cin>>n>>m>>q;
    int i;
    memset(h,-1,sizeof h);
    for(i=1;i<=m;i++){
        int a,b;
        cin>>a>>b;
        add(a,b);
        add(b,a);
    }
    cnt=n;
    dfs(1);
    depth[1]=1;
    dfs2(1);
    while(q--){
        int x,y;
        cin>>x>>y;
        int p=lca(x,y);
        cout<<(depth[x]+depth[y])/2-depth[p]<<endl;
    }
    return 0;
}
View Code
没有人不辛苦,只有人不喊疼
原文地址:https://www.cnblogs.com/ctyakwf/p/13769467.html