• 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
    ", 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 }
  • 相关阅读:
    SpringBoot20 集成SpringSecurity02 -> 利用SpringSecurity进行前后端分离的登录验证
    Angular问题04 模块导入错误???、BrowserModule模块重复加载???、material模块引入后报错
    基于http的多进程并发文件服务器
    准备面试的那些事儿2
    ubuntu中解决/usr/bin/ld: cannot find -lxxx
    kafka学习之相关命令
    linux中制作动态库
    kafka之c接口常用API------librdkafka
    kafka入门:简介、使用场景、设计原理、主要配置及集群搭建(转)
    <c和指针>学习笔记6输入输出函数
  • 原文地址:https://www.cnblogs.com/767355675hutaishi/p/4451864.html
Copyright © 2020-2023  润新知