zju zoj 2588 求割边模板 边双连通
终极模板
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int N = 10010;
const int M = 100010;
int min(int a,int b){
return a>b?b:a;
}
struct EDGE{
int to,next,id;
}edge[2*M];
int n,m,tot,tdfn,nbridge;
int head[N],vis[N],low[N],dfn[N],bridge[M];
void add(int a,int b,int edgeid){
//这种方法判重边很慢
/* for(j=head[a];j!=-1;j=edge[j].next){
if(b==edge[j].to)
break;
}
if(j!=-1)
{
edge[j].tag=1;
edge[j^1].tag=1;
return ;
}*/
edge[tot].to=b;
edge[tot].id=edgeid;
edge[tot].next=head[a];
head[a]=tot++;
edge[tot].to=a;
edge[tot].id=edgeid;
edge[tot].next=head[b];
head[b]=tot++;
}
void dfs(int u,int fa){
int i,v;low[u]=dfn[u]=++tdfn;vis[u]=1;
for(i=head[u];i!=-1;i=edge[i].next){
v=edge[i].to;
if(vis[v]==1&&edge[i].id!=fa) low[u]=min(low[u],dfn[v]);
else if(!vis[v])
{
dfs(v,edge[i].id);
low[u]=min(low[u],low[v]);
if(low[v]>dfn[u]){
bridge[edge[i].id]=++nbridge;
}
}
}
vis[u]=2;
}
void init(){
int i;
tdfn=1;tot=0;nbridge=0;
for(i=0;i<=n;i++) head[i]=-1;
for(i=1;i<=m;i++) bridge[i]=0;
for(i=1;i<=n;i++) vis[i]=0;
}
int main()
{
int i,k,t;
int u,v;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);
init();
for(k=1;k<=m;k++)
{
scanf("%d%d",&u,&v);
add(u,v,k);
}
dfs(1,0);
printf("%d\n",nbridge);
for(i=1,k=nbridge;i<=m;i++)
{
if(bridge[i])
{
printf("%d",i);
if(--k) printf(" ");
}
}
if(nbridge) printf("\n");
if(t) printf("\n");
}
return 0;
}