给出含有n个顶点和m条边的连通无向图,求出所有割边的序号。
1 #include <cstdio> 2 #include <cstring> 3 #define clr(a) memset(a,0,sizeof(a)) 4 #define N 10005 5 #define M 100005 6 #define MIN(a,b) ((a)>(b)?(b):(a)) 7 typedef struct NodeStr //边结点 8 { 9 int j, tag, id; //j 为另一个顶点的序号, tag 为重边的数量, id 为序号 10 struct NodeStr *next; //下一个边结点 11 }Node; 12 int n, m; //顶点数、边数 13 int nid; //nid 为输入时边的序号 14 Node mem[M*2]; int memp; //mem 为存储边结点的数组, memp 为 mem 数组中的序号 15 Node *e[N]; //邻接表 16 int bridge[M]; //bridge[i]为 1,则第 i+1 条边为割边 17 int nbridge; //求得的割边的数目 18 int low[N], dfn[N]; //low[i]为顶点 i 可达祖先的最小编号,dfn[i]为深度优先数 19 int visited[N]; //visited[i]为 0-未访问,为 1-已访问,为 2-已访问且已检查邻接顶点 20 //在邻接表中插入边(i,j),如果有重边,则只是使得相应边结点的 tag 加 1 21 int addEdge( Node *e[], int i, int j ) 22 { 23 Node* p; 24 for( p=e[i]; p!=NULL; p=p->next ) 25 { 26 if( p->j==j ) break; 27 } 28 if( p!=NULL ) //(i,j)为重边 29 { p->tag++; return 0; } 30 p = &mem[memp++]; 31 p->j = j; p->next = e[i]; e[i] = p; p->id = nid; p->tag = 0; 32 return 1; 33 } 34 35 //参数含义: i-当前搜索的顶点, father-i 的父亲顶点, dth-搜索深度 36 void DFS( int i, int father, int dth ) 37 { 38 visited[i] = 1; dfn[i] = low[i] = dth; 39 Node *p; 40 for( p=e[i]; p!=NULL; p=p->next ) 41 { 42 int j = p->j; 43 if( j!=father && visited[j]==1 ) 44 low[i] = MIN( low[i], dfn[j] ); 45 if( visited[j]==0 ) //顶点 j 未访问 46 { 47 DFS( j, i, dth+1 ); 48 low[i] = MIN( low[i], low[j] ); 49 if( low[j]>dfn[i] && !p->tag ) //重边不可能是割边 50 bridge[p->id] = ++nbridge; 51 } 52 } 53 visited[i] = 2; 54 } 55 int main( ) 56 { 57 int i, j, k, T; //T 为测试数据数目 58 scanf( "%d", &T ); 59 while( T-- ) 60 { 61 scanf( "%d%d", &n, &m ); 62 memp = 0; nid = 0; clr(e); 63 for( k=0; k<m; k++, nid++ ) //读入边,存储到邻接表中 64 { 65 scanf( "%d%d", &i, &j ); 66 addEdge( e, i-1, j-1 ); addEdge( e, j-1, i-1 ); 67 bridge[nid] = 0; 68 } 69 nbridge = 0; clr(visited); 70 //从顶点 0 出发进行 DFS 搜索,顶点 0 是根结点,所以第 2 个参数为-1 71 DFS( 0, -1, 1 ); 72 printf( "%d ", nbridge ); //输出割边的信息 73 74 /* 75 for( i=0, k=nbridge; i<m; i++ ) 76 { 77 if( bridge[i] ) 78 { 79 printf( "%d", i+1 ); 80 if( --k ) printf( " " ); 81 } 82 } 83 */ 84 int Y=0; 85 for(i=0;i<m;i++) 86 { 87 if(bridge[i]) 88 { 89 if(Y++>0) 90 printf(" "); 91 printf("%d",i+1); 92 } 93 } 94 95 if( nbridge ) 96 puts(""); 97 if( T ) 98 puts(""); 99 } 100 return 0; 101 }