Burning Bridges 求tarjan求割边

                        Burning Bridges

 

给出含有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\n", 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 }

 

posted @ 2015-04-23 21:37  daydaycode  阅读(144)  评论(0编辑  收藏  举报