#include <iostream> #include <cstring> #include <string> #include <cstdio> #include <cmath> #include <algorithm> #include <vector> #include <queue> #include <map> #define inf 0x3f3f3f3f #define eps 1e-6 #define ll __int64 using namespace std; #define N 10010 #define M 100010 struct node//边结点 { int v,tag,id;//v为所连接的另一个结点,tag为重边数,id为序号 node *next; }; int n,m;//点,边数 int nid;//输入时边的序号 node mem[M*2];int memp;//mem为存储边结点的数组,memp为mem数组序号 node *e[N];//邻接表 int brig[M];//brig[i]=1表示第i+1条边为割边 int nbrig;//求得割边的数目 int low[N],dfn[N];//low[i]为顶点i可达祖先的最小编号,dfn[i]为深度优先数 int vis[N];//0未访问 1已访问 2已访问且已检查邻接结点 //在邻接表中插入边(i,j),若有重边,则只把相应边结点的tag+1 int addedge(int i,int j) { node* p; for(p=e[i];p!=NULL;p=p->next) if(p->v==j) break; if(p!=NULL) { p->tag++; return 0; } p=&mem[memp++]; p->v=j; p->next=e[i]; e[i]=p; p->id=nid; p->tag=0; return 1; } //参数含义:i为当前搜索的顶点,father为i的父节点,dth为搜索深度 void dfs(int i,int father,int dth) { vis[i]=1; dfn[i]=low[i]=dth; node* p; for(p=e[i];p!=NULL;p=p->next) { int j=p->v; if(j!=father&&vis[j]) low[i]=min(low[i],dfn[j]); if(!vis[j]) { dfs(j,i,dth+1); low[i]=min(low[i],low[j]); if(low[j]>dfn[i]&&!p->tag) brig[p->id]=++nbrig; } } vis[i]=2; } void init() { memp=nid=nbrig=0; memset(e,0,sizeof e); memset(brig,0,sizeof brig); memset(vis,0,sizeof vis); } int main() { int t,i,j,a,b; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); init(); for(i=0;i<m;i++) { scanf("%d%d",&a,&b); addedge(a-1,b-1); addedge(b-1,a-1); nid++; } dfs(0,-1,1); printf("%d\n",nbrig); for(i=0,j=nbrig;i<m;i++) { // printf("i:%d brig[i]:%d\n",i+1,brig[i]); if(brig[i]) { printf("%d",i+1); if(--j) putchar(' '); } } if(nbrig) puts(""); if(t) puts(""); } return 0; }
zoj2588 Burning Bridges --- 求割边,布布扣,bubuko.com
时间: 2024-10-13 11:51:12