题意

一个无向图可以有重边,下面 个操作,每次在两个点间连接一条有向边,每次连接后整个无向图还剩下多少桥(注意是要考虑之前连了的边,每次回答是在上一次的基础之上)

分析

求出桥来之后缩点,缩点运用并查集实现,每一个点组用父亲节点代表。emm,好像就这样。

PS:

虽说楼上大佬说并查集实现更快,但我还是比 慢啊。我太菜了/kk

代码

#include<bits/stdc++.h>
#define ll long long
const int N=2e5+5,INF=0x3f3f3f3f,mod=998244353;
using namespace std;

inline int read()
{
    register int x=0,f=1;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}
    while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
    return x*f;
}

int tot,nxt[N*2],point[N],v[N*2],num,dfn[N],low[N],stack_[N],ss,nn;
int belong[N],f[N],father[N],ans;
bool vis[N];

void cl()
{
    tot=0;memset(point,0,sizeof(point));
    memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low));
    nn=0;ss=0;num=0;ans=0;
}

void addline(int x,int y)
{
    nxt[++tot]=point[x];point[x]=tot;v[tot]=y;
    nxt[++tot]=point[y];point[y]=tot;v[tot]=x;   
}

int find(int x)
{
    return x==f[x]?x:f[x]=find(f[x]);
}

void tarjan(int x,int fa)
{
    dfn[x]=low[x]=++nn;vis[x]=1;stack_[++ss]=x;
    bool fff=0;
    for (int i=point[x];i;i=nxt[i])
    {
        if (v[i]==fa && !fff){fff=1; continue;}
        if (!dfn[v[i]])
        {
            father[v[i]]=x;
            tarjan(v[i],x);
            low[x]=min(low[x],low[v[i]]);
            if (low[v[i]]>dfn[x]) ans++;
            else f[find(v[i])]=find(x);
        }
        else low[x]=min(low[x],dfn[v[i]]);
    }
}

int lca(int x,int y)
{
    if (dfn[x]<dfn[y]) swap(x,y);
    while (dfn[x]>dfn[y])
    {
        int xx=find(x),ff=find(father[x]);
        if (xx!=ff) ans--,f[xx]=ff;
        x=father[x];
    }
    while (y!=x)
    {
        int xx=find(y),ff=find(father[y]);
        if (xx!=ff) ans--,f[xx]=ff;
        y=father[y];
    }
    return ans;
}

int main()
{
    int cnt=0,n,m,i,q;
    n=read();m=read();
    while(n&&m)
    {
        cl();int x,y;
        for (i=1;i<=m;i++)
        {
            x=read();y=read();
            addline(x,y);
        }
        for (i=1;i<=n;i++) f[i]=i;
        tarjan(1,0);
        q=read();
        printf("Case %d:\n",++cnt);
        for (i=1;i<=q;i++)
        {
            x=read();y=read();
            printf("%d\n",lca(x,y));
        }
        printf("\n");
        n=read();m=read();
    }
}