ZOJ 2588 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 std;

 7 

 8 struct node

 9 {

10     int u ;

11     int v;

12     int next ;

13     int num ;

14 }p[200100];

15 int dfn[200100],low[200100] ;//dfn深度优先遍历生成树的顺序,low表示该节点能够到达的祖先的最小编号

16 int bridge[200100] ,nbrid,vis[200010];//桥的编号,割边的条数,vis表示该点是否访问过

17 int cnt,head[200100],tot ;

18 

19 void Init()

20 {

21     cnt = nbrid = tot= 0 ;

22     memset(head,-1,sizeof(head)) ;

23     memset(vis,0,sizeof(vis)) ;

24 }

25 void addedge(int u,int v,int id)

26 {

27     //p[cnt].u = u ;

28     p[cnt].v = v ;

29     p[cnt].num = id ;

30     p[cnt].next = head[u] ;

31     head[u] = cnt ++ ;

32     //p[cnt].u = v ;

33     p[cnt].v = u ;

34     p[cnt].num = id ;

35     p[cnt].next = head[v] ;

36     head[v] = cnt ++ ;

37 }

38 

39 void DFS(int u,int fu)

40 {

41     dfn[u] = low[u] = tot++ ;

42     vis[u] = 1 ;

43     for(int i = head[u] ; i != -1 ; i = p[i].next)

44     {

45         int v = p[i].v;

46         if(p[i].num != fu && vis[v] )

47         {

48             low[u] = min(low[u],dfn[v]) ;

49         }

50         else if( !vis[v] )

51         {

52             DFS(v,p[i].num) ;

53             low[u] = min(low[u],low[v]) ;

54             if(low[v] > dfn[u])

55             {

56                 bridge[++nbrid] = p[i].num;

57             }

58         }

59     }

60 }

61 int main()

62 {

63     int T ,N,M,u,v;

64     scanf("%d",&T) ;

65     while(T--)

66     {

67         Init() ;

68         scanf("%d %d",&N,&M) ;

69         for(int i = 1 ; i <= M ; i++)

70         {

71             scanf("%d %d",&u,&v) ;

72             addedge(u,v,i) ;

73         }

74         DFS(1,-1) ;

75         sort(bridge+1,bridge+1+nbrid) ;

76         printf("%d\n",nbrid) ;

77         for(int i = 1 ; i <= nbrid ; i++)

78         {

79             if(i != nbrid)

80             printf("%d ",bridge[i]) ;

81             else printf("%d\n",bridge[i]) ;

82         }

83         if(T)puts("") ;

84     }

85     return 0;

86 }
View Code

 

鹏哥说我那样写的太丑了,非给我改成下边的样子

 1 #include <iostream>

 2 #include <cstdio>

 3 #include <cstring>

 4 #include <algorithm>

 5 

 6 using namespace std;

 7 

 8 struct node

 9 {

10     int u ;

11     int v;

12     int next ;

13     int num ;

14 }p[200100];

15 int dfn[200100],low[200100] ;

16 int bridge[200100] ,nbrid,vis[200010];

17 int cnt,head[200100],tot ;

18 int fb[200100];

19 void Init()

20 {

21     cnt = nbrid = tot= 0 ;

22     memset(head,-1,sizeof(head)) ;

23     memset(vis,0,sizeof(vis)) ;

24     memset(fb,0,sizeof(fb));

25     memset(dfn,0,sizeof(dfn));

26     memset(low,0,sizeof(low));

27 }

28 void addedge(int u,int v,int id)

29 {

30     //p[cnt].u = u ;

31     p[cnt].v = v ;

32     p[cnt].num = id ;

33     p[cnt].next = head[u] ;

34     head[u] = cnt ++ ;

35     //p[cnt].u = v ;

36     p[cnt].v = u ;

37     p[cnt].num = id ;

38     p[cnt].next = head[v] ;

39     head[v] = cnt ++ ;

40 }

41 void DFS(int u)

42 {

43     dfn[u] = low[u] = ++tot;

44     //vis[u] = 1 ;

45     for(int i = head[u] ; i != -1 ; i = p[i].next)

46     {

47         int v=p[i].v;

48         if(fb[i^1])continue;

49         fb[i]=1;

50         if(dfn[v] )//如果该点没被访问过dfn自然为0,所以不用vis数组也可

51         {

52             low[u] = min(low[u],dfn[v]) ;

53         }

54         else

55         {

56             DFS(v) ;

57             low[u] = min(low[u],low[v]) ;

58             if(low[v] > dfn[u])

59             {

60                 bridge[++nbrid] = p[i].num;

61             }

62         }

63     }

64 }

65 int main()

66 {

67     int T ,N,M,u,v;

68     scanf("%d",&T) ;

69     while(T--)

70     {

71         Init() ;

72         scanf("%d %d",&N,&M) ;

73         for(int i = 1 ; i <= M ; i++)

74         {

75             scanf("%d %d",&u,&v) ;

76             addedge(u,v,i) ;

77         }

78         DFS(1) ;

79         sort(bridge+1,bridge+1+nbrid) ;

80         printf("%d\n",nbrid) ;

81         for(int i = 1 ; i <= nbrid ; i++)

82         {

83             if(i != nbrid)

84             printf("%d ",bridge[i]) ;

85             else printf("%d\n",bridge[i]) ;

86         }

87         if(T)puts("") ;

88     }

89     return 0;

90 }
View Code

 

你可能感兴趣的:(bridge)