先把图进行e-DCC缩点,得到若干桥连接的e-DCC。
给的图是联通的,所以得到的e-DCC图是一棵树。
初始每个树边都是桥。
每家一个边x-y。会让树上 c[x] - > c[y] (c[x]: x点所在的e-DCC编号) 点路径连成环,路径上的树边所表示的桥均会变成非桥边。
所以我们可以每次跑x-y路径上的所有边,若某个边 a-b,是桥边,则让总桥数ans-1,且让这条边标记为非桥边。
每次路径最长为N,最多Q次,复杂度O(M+N*Q)
#include
using namespace std;
typedef long long ll;
#define ls (o<<1)
#define rs (o<<1|1)
#define pb push_back
const double PI= acos(-1.0);
const int M = 4e5+7;
int head[M],cnt=1,head_c[M],cnt_c=1;
struct EDGE{int to,nxt,w;}ee[M*2],ee_c[M*2];
void add(int x,int y,int w){ee[++cnt].nxt=head[x],ee[cnt].w=w,ee[cnt].to=y,head[x]=cnt;}
void add_c(int x,int y,int w){ee_c[++cnt_c].nxt=head_c[x],ee_c[cnt_c].w=w,ee_c[cnt_c].to=y,head_c[x]=cnt_c;}
int dfn[M],low[M],nm;
bool bridge[M];
void tarjan(int x,int in_edge)
{
dfn[x]=low[x]=++nm;
for(int i=head[x];i;i=ee[i].nxt)
{
int y=ee[i].to;
if(!dfn[y])
{
tarjan(y,i);
low[x]=min(low[x],low[y]);
if(low[y]>dfn[x])bridge[i]=bridge[i^1]=true;
}
else if(i!=(in_edge^1))low[x]=min(low[x],dfn[y]);
}
}
int c[M],fa[M];
int tg[M];//这条边是否时桥边
int sz;//e-DCC个数
int get(int x)
{
if(x==fa[x])return x;
return fa[x]=get(fa[x]);
}
void mg(int x,int y)
{
int gx=get(x),gy=get(y);
if(gx!=gy)fa[gx]=gy;
}
void dfs(int x)
{
c[x]=sz;
for(int i=head[x];i;i=ee[i].nxt)
{
int y=ee[i].to;
if(c[y]||bridge[i])continue;
dfs(y);
}
}
int n,m;
int d[M];//深度
int f[M][21];//点i的 (1<q;
for(int i=1;i<=n;i++)d[i]=0;
q.push(1);d[1]=1;
while(q.size())
{
int x=q.front();q.pop();
for(int i=head_c[x];i;i=ee_c[i].nxt)
{
int y=ee_c[i].to,w=ee_c[i].w;
if(d[y])continue;
d[y]=d[x]+1;f[y][0]=x;q.push(y);
}
}
for(int k=1;k<=20;k++)
for(int i=1;i<=n;i++)
f[i][k]=f[f[i][k-1]][k-1];
}
int lca(int x,int y)
{
if(d[x]>d[y])swap(x,y);
for(int i=20;i>=0;i--)
if(d[f[y][i]]>=d[x])y=f[y][i];
if(x==y)return x;
for(int i=20;i>=0;i--)
if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];
return f[x][0];
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int u,v,T=0;
while(cin>>n>>m)
{
if(n==0)break;++T;
cnt=cnt_c=1;sz=0;
for(int i=1;i<=4*n;i++)head[i]=head_c[i]=bridge[i]=dfn[i]=c[i]=0,fa[i]=i;
for(int i=1;i<=m;i++)cin>>u>>v,add(u,v,1),add(v,u,1);
int q;
tarjan(1,0);
cin>>q;
for(int i=1;i<=n;i++)
{
if(c[i])continue;
++sz;dfs(i);
}
for(int i=1;i<=n;i++){
// cout<>u>>v;
x=c[u],y=c[v];
int tp=lca(x,y);
// cout<