【luogu2783】 有机化学之神偶尔会做作弊 [tarjan 缩点][LCA]

P2783 有机化学之神偶尔会做作弊 

缩点 然后LCA x,y两点之间的距离为dep[x]+dep[y]-2dep[lca]+1

死于各种缩点之后忘记用bl

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=10000+50,M=50000+50,inf=0x3f3f3f3f;
int n,m,q,ans=0,f[N][25],dep[N];
int idx=0,Bcnt=0,dfn[N],low[N],bl[N];
bool inst[N];
stack<int>s;
template<class t>void rd(t &x){
    x=0;int w=0;char ch=0;
    while(!isdigit(ch)) w|=ch=='-',ch=getchar();
    while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    x=w?-x:x;
}

int head[N],tot=0;
struct edge{int u,v,nxt;}e[M<<1],e2[M<<1];
void add(int u,int v){
    e[++tot]=(edge){u,v,head[u]};head[u]=tot;
}

void tarjan(int u,int fa){
    dfn[u]=low[u]=++idx;
    s.push(u),inst[u]=1;
    for(int i=head[u],v;i;i=e[i].nxt){
        v=e[i].v;
        if(v!=fa){
            if(!dfn[v]) tarjan(v,u),low[u]=min(low[u],low[v]);
            else if(inst[v]&&low[u]>dfn[v]) low[u]=dfn[v];    
        }
    }
    if(low[u]==dfn[u]){
        ++Bcnt;
        int v;
        do{
            v=s.top(),s.pop();
            bl[v]=Bcnt,inst[v]=0;
        }while(u!=v);
    }
}

int head2[N],tot2=0;
void add2(int u,int v){
    e2[++tot2]=(edge){u,v,head2[u]};head2[u]=tot2;
} 
void dfs(int u,int fa){
    dep[u]=dep[fa]+1;
    f[u][0]=fa;
    for(int i=1;i<=20;++i){
        if(dep[u]<(1<<i)) break;
        f[u][i]=f[f[u][i-1]][i-1];
    }
    for(int i=head2[u];i;i=e2[i].nxt){
        if(e2[i].v==fa) continue;
        dfs(e2[i].v,u);
    }
}
int LCA(int a,int b){
    if(dep[a]>dep[b]) swap(a,b);
    for(int i=20;i>=0;--i){
        if(dep[f[b][i]]<dep[a]) continue;
        b=f[b][i];
    }
    if(b==a) return a;
    for(int i=20;i>=0;--i){
        if(f[a][i]==f[b][i]) continue;
        a=f[a][i],b=f[b][i];
    }
    return f[a][0];
}

void print(int x){
    int num[N];
    memset(num,0,sizeof(num));
    if(!x) {puts("0");return;}
    if(x<0) {putchar('-');x=0-x;}
    while(x) num[++num[0]]=(x&1),x>>=1;
    for(int i=num[0];i>0;--i) printf("%d",num[i]);
    printf("\n");
}

int main(){
    //freopen("in.txt","r",stdin);
    rd(n),rd(m);
    for(int i=1,u,v;i<=m;++i) rd(u),rd(v),add(u,v),add(v,u);
    for(int i=1;i<=n;++i)
    if(!dfn[i]) tarjan(i,0);
    for(int i=1;i<=m;++i)
    if(bl[e[i<<1].u]!=bl[e[i<<1].v]) add2(bl[e[i<<1].u],bl[e[i<<1].v]),add2(bl[e[i<<1].v],bl[e[i<<1].u]);
    rd(q);
    dfs(1,0);
    for(int i=1,x,y,lca;i<=q;++i){
        rd(x),rd(y),lca=LCA(bl[x],bl[y]);
        print(dep[bl[x]]+dep[bl[y]]-dep[lca]*2+1);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/lxyyyy/p/11161685.html