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
",nbrid) ;
77         for(int i = 1 ; i <= nbrid ; i++)
78         {
79             if(i != nbrid)
80             printf("%d ",bridge[i]) ;
81             else printf("%d
",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
",nbrid) ;
81         for(int i = 1 ; i <= nbrid ; i++)
82         {
83             if(i != nbrid)
84             printf("%d ",bridge[i]) ;
85             else printf("%d
",bridge[i]) ;
86         }
87         if(T)puts("") ;
88     }
89     return 0;
90 }
View Code
原文地址:https://www.cnblogs.com/luyingfeng/p/3905188.html