AcWing397 逃不掉的路(边双)

无向图缩点的low值定义是经过一条B边能够到的点的dfn的最小值

如果low[v]>=low[u],说明有割点,但是要特判树边,如果low[v]>low[u],说明是有割边,但是要特判重边,本题很显然边双里的点都是不必要的

只有桥是必要的,先缩点之后跑一下lca

#include<bits/stdc++.h>
using namespace std;
const int N=5e5+10;
int h[N],ne[N],idx,e[N],cnt;
int dfn[N],low[N],isce[N];
int f[N][21];
int ecc[N];
int depth[N];
int fa[N];
vector<int> g[N];
void add(int a,int b){
    e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
int n,m,times,ans;
void tarjan(int u){
    dfn[u]=low[u]=++times;
    int i;
    for(i=h[u];i!=-1;i=ne[i]){
        int j=e[i];
        if(!dfn[j]){
            fa[j]=u;
            tarjan(j);
            low[u]=min(low[u],low[j]);
            if(dfn[u]<low[j]) isce[j]=1;
        }
        else if(j!=fa[u]) low[u]=min(low[u],dfn[j]);
    }
}
void dfs(int u,int x){
    ecc[u]=x;
    for(int i=h[u];i!=-1;i=ne[i]){
        int j=e[i];
        if(ecc[j]||fa[j]==u&&isce[j]||fa[u]==j&&isce[u])
        continue;
        dfs(j,x);
    }
}
void bfs(){
    queue<int> q;
    q.push(1);
    memset(depth,0x3f,sizeof depth);
    depth[0]=0,depth[1]=1;
    while(q.size()){
        int t=q.front();
        q.pop();
        int i;
        for(i=0;i<(int)g[t].size();i++){
            int j=g[t][i];
            if(depth[j]>depth[t]+1){
                depth[j]=depth[t]+1;
                q.push(j);
                f[j][0]=t;
                for(int k=1;k<=20;k++){
                    f[j][k]=f[f[j][k-1]][k-1];
                }
            }
        }
    }
}
int lca(int a,int b){
    if(depth[a]<depth[b])
        swap(a,b);
    int i;
    for(i=20;i>=0;i--){
        if(depth[f[a][i]]>=depth[b]){
            a=f[a][i];
        }
    }
    if(a==b)
        return a;
    for(i=20;i>=0;i--){
        if(f[a][i]!=f[b][i]){
            a=f[a][i];
            b=f[b][i];
        }
    }
    
    return f[a][0];
}
int main(){
    ios::sync_with_stdio(false);
    cin>>n>>m;
    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);
    }
    tarjan(1);
    for(i=1;i<=n;i++){
        if(!ecc[i]){
            dfs(i,++cnt);
        }
    }
    for(i=1;i<=n;i++){
        int j;
        for(j=h[i];j!=-1;j=ne[j]){
            int k=e[j];
            if(ecc[i]==ecc[k])
                continue;
            g[ecc[i]].push_back(ecc[k]);
        }
    }
    bfs();
    int qi;
    cin>>qi;
    while(qi--){
        int x,y;
        cin>>x>>y;
        x=ecc[x],y=ecc[y];
        int p=lca(x,y);
        cout<<depth[x]+depth[y]-2*depth[p]<<endl;
    }
}
View Code

 

posted @ 2020-05-26 08:59  朝暮不思  阅读(233)  评论(0编辑  收藏  举报