//Tarjan求桥
void tarjan(int now,int id){
dfn[now]=low[now]=++dfnc;
for(int i=head[now];i!=-1;i=b[i].next){
if(i==(id^1)) continue;
int u=b[i].to;
if(!dfn[u]){
tarjan(u,i);
low[now]=min(low[now],low[u]);
if(dfn[now]<low[u]) bridge[i]=bridge[i^1]=true;
} else {
low[now]=min(low[now],dfn[u]);
}
}
}
//求边双连通分量
void dfs(int now,int id){
shuyu[now]=id;
for(int i=head[now];i!=-1;i=b[i].next){
int u=b[i].to;
if(shuyu[u]) continue;
if(!bridge[i]) dfs(u,id);
}
}
//边双缩点
for(int i=1;i<=n;i++){
for(int j=head[i];j!=-1;j=b[j].next){
int u=b[j].to;
if(shuyu[i]!=shuyu[u]){
ad(shuyu[i],shuyu[u]);
ad(shuyu[u],shuyu[i]);
}
}
}