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 }
时间: 2024-10-05 23:59:19

Burning Bridges 求tarjan求割边的相关文章

ZOJ 2588 Burning Bridges(无向图求割边)

ZOJ 2588 Burning Bridges 链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2588 题意:给定一个无向图连通图,(其中可能有重边),要求去掉一条边之后,使得整个图不再连通.输出这些符合条件的边的序号. 思路:这就是一个简单的无向图求割边,需要注意的是这个无向图有重边,重边一定不是割边. 代码: /*========================================= 无向图求割点

ZOJ 1588 Burning Bridges (tarjan求割边)

题目链接 题意 : N个点M条边,允许有重边,让你求出割边的数目以及每条割边的编号(编号是输入顺序从1到M). 思路 :tarjan求割边,对于除重边以为中生成树的边(u,v),若满足dfn[u] < low[v],则边(u,v)是割边. 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 6 using namespace st

ZOJ Problem - 2588 Burning Bridges tarjan算法求割边

题意:求无向图的割边. 思路:tarjan算法求割边,访问到一个点,如果这个点的low值比它的dfn值大,它就是割边,直接ans++(之所以可以直接ans++,是因为他与割点不同,每条边只访问了一遍). 需要注意的就是此处有多重边,题目中要求输出确定的不能被删除的边,而多重边的保留不是可以确定的,所以多重边都是不可以被保留的,我们可以在邻接表做一个flag的标记,判断他是不是多重边. 注意建图的时候数组应该是m × 2,因为这里是无向边,当心RE! 注意输出的时候编号是必须要拍好序再输出. 还有

zoj2588 Burning Bridges --- 求割边

#include <iostream> #include <cstring> #include <string> #include <cstdio> #include <cmath> #include <algorithm> #include <vector> #include <queue> #include <map> #define inf 0x3f3f3f3f #define eps 1e-

zoj 2588 Burning Bridges【双连通分量求桥输出桥的编号】

Burning Bridges Time Limit: 5 Seconds      Memory Limit: 32768 KB Ferry Kingdom is a nice little country located on N islands that are connected by M bridges. All bridges are very beautiful and are loved by everyone in the kingdom. Of course, the sys

ZOJ 2588 Burning Bridges 求无向图桥 边双连通裸题

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1588 binshen的板子: #include <stdio.h> #include <string.h> #include <iostream> #include <algorithm> #include <vector> #include <queue> #include <set> #i

HDU 4738 Caocao&#39;s Bridges tarjan求桥

Caocao's Bridges Problem Description Caocao was defeated by Zhuge Liang and Zhou Yu in the battle of Chibi. But he wouldn't give up. Caocao's army still was not good at water battles, so he came up with another idea. He built many islands in the Chan

tarjan求割边割点

tarjan求割边割点 内容及代码来自http://m.blog.csdn.net/article/details?id=51984469 割边:在连通图中,删除了连通图的某条边后,图不再连通.这样的边被称为割边,也叫做桥.割点:在连通图中,删除了连通图的某个点以及与这个点相连的边后,图不再连通.这样的点被称为割点.DFS搜索树:用DFS对图进行遍历时,按照遍历次序的不同,我们可以得到一棵DFS搜索树. 树边:在搜索树中的蓝色线所示,可理解为在DFS过程中访问未访问节点时所经过的边,也称为父子边

【模板】【hdu4738】Caocao&#39;s Bridges——tarjan求桥

题目链接 题目大意: 曹操有N个岛,这些岛用M座桥连接起来,每座桥有士兵把守(也可能没有), 诸葛亮把所有炸弹都带走了,只留下一枚给周瑜(真狠). 周瑜想让这N个岛不连通,但需要派出不小于守桥士兵数的人去炸桥,因为只有一枚炸弹,因此只够炸掉一座桥. 分析: 很明显的求代价最小的桥,当然这道题有几个特殊的地方: 1.图本来就不联通,输出0: 2.无解(不存在桥),输出-1: 3.没人把守,但你还是得派一个人炸桥,输出1: 4.一般情况,输出最小代价. 剩下的就是模板了,不过需要注意的一点是,这道题