1
1
use graph:: Graph ;
2
2
use :: std:: cmp:: min;
3
3
4
- // Strongly connected, 2-vertex-connected, and 2-edge-connected components
5
- // should handle multiple-edges and self-loops
6
- // USAGE: 1) new(); 2) add_edge(...); 3) compute_bcc();
7
- // 4) use is_cut_vertex(vertex_index) or is_cut_edge(2 * edge_index)
8
-
9
- #[ derive( Clone ) ]
10
- pub struct CCVertex {
11
- pub cc : usize ,
12
- low : usize ,
13
- vis : usize ,
14
- }
15
-
16
- pub struct CCGraph < ' a > {
4
+ // Represents the decomposition of a graph into any of its:
5
+ // - Connected components (CC),
6
+ // - Strongly connected components (SCC),
7
+ // - 2-edge-connected components (2ECC),
8
+ // - 2-vertex-connected components (2VCC)
9
+ // Multiple-edges and self-loops should be correctly handled.
10
+ pub struct ConnectivityGraph < ' a > {
17
11
pub graph : & ' a Graph ,
18
- pub vdata : Vec < CCVertex > ,
19
- pub vcc : Vec < usize > ,
12
+ pub cc : Vec < usize > , // stores id of a vertex's CC, SCC or 2ECC
13
+ pub vcc : Vec < usize > , // stores id of an edge's 2VCC
20
14
pub num_cc : usize ,
21
- pub num_vcc : usize ,
22
- t : usize ,
23
- verts : Vec < usize > ,
24
- edges : Vec < usize >
15
+ pub num_vcc : usize
25
16
}
26
17
27
- impl < ' a > CCGraph < ' a > {
28
- pub fn new ( graph : & ' a Graph , is_directed : bool ) -> CCGraph {
29
- let data = CCVertex { cc : 0 , low : 0 , vis : 0 } ;
30
- let mut cc_graph = CCGraph {
18
+ impl < ' a > ConnectivityGraph < ' a > {
19
+ // Computes the SCCs of a directed graph in reverse topological order, or
20
+ // the 2ECCs/2VCCS of an undirected graph. Can also get CCs by passing an
21
+ // undirected graph with is_directed == true.
22
+ pub fn new ( graph : & ' a Graph , is_directed : bool ) -> ConnectivityGraph {
23
+ let mut connect = ConnectivityGraph {
31
24
graph : graph,
32
- vdata : vec ! [ data ; graph. num_v( ) ] ,
25
+ cc : vec ! [ 0 ; graph. num_v( ) ] ,
33
26
vcc : vec ! [ 0 ; graph. num_e( ) ] ,
34
27
num_cc : 0 ,
35
- num_vcc : 0 ,
36
- t : 0 ,
37
- verts : Vec :: new ( ) ,
38
- edges : Vec :: new ( )
28
+ num_vcc : 0
39
29
} ;
40
- for i in 0 ..graph. num_v ( ) {
41
- if cc_graph. vdata [ i] . vis == 0 {
30
+ let mut t = 0 ;
31
+ let mut vis = vec ! [ 0 ; graph. num_v( ) ] ;
32
+ let mut low = vec ! [ 0 ; graph. num_v( ) ] ;
33
+ let mut verts = Vec :: new ( ) ;
34
+ let mut edges = Vec :: new ( ) ;
35
+ for u in 0 ..graph. num_v ( ) {
36
+ if vis[ u] == 0 {
42
37
if is_directed {
43
- cc_graph . scc ( i ) ;
38
+ connect . scc ( u , & mut t , & mut vis , & mut low , & mut verts ) ;
44
39
}
45
40
else {
46
- cc_graph. bcc ( i, 0 ) ; // TODO: default 2nd arg at root
41
+ connect. bcc ( u, graph. num_e ( ) + 1 , & mut t, & mut vis,
42
+ & mut low, & mut verts, & mut edges) ;
47
43
}
48
44
}
49
45
}
50
- cc_graph
46
+ connect
51
47
}
52
48
53
- // SCCs form a DAG whose components are numbered in reverse topological order.
54
- fn scc ( & mut self , u : usize ) {
55
- self . t += 1 ;
56
- self . vdata [ u] . low = self . t ;
57
- self . vdata [ u] . vis = self . t ;
58
- self . verts . push ( u) ;
49
+ fn scc ( & mut self , u : usize , t : & mut usize , vis : & mut [ usize ] ,
50
+ low : & mut [ usize ] , verts : & mut Vec < usize > ) {
51
+ * t += 1 ;
52
+ vis [ u] = * t;
53
+ low [ u] = * t;
54
+ verts. push ( u) ;
59
55
for ( _, v) in self . graph . adj_list ( u) {
60
- if self . vdata [ v] . vis == 0 { self . scc ( v) ; }
61
- if self . vdata [ v] . cc == 0 {
62
- self . vdata [ u] . low = min ( self . vdata [ u] . low , self . vdata [ v] . low ) ;
63
- }
56
+ if vis[ v] == 0 { self . scc ( v, t, vis, low, verts) ; }
57
+ if self . cc [ v] == 0 { low[ u] = min ( low[ u] , low[ v] ) ; }
64
58
}
65
- if self . vdata [ u] . vis <= self . vdata [ u] . low {
59
+ if vis [ u] == low [ u] {
66
60
self . num_cc += 1 ;
67
- while let Some ( v) = self . verts . pop ( ) {
68
- self . vdata [ v] . cc = self . num_cc ;
61
+ while let Some ( v) = verts. pop ( ) {
62
+ self . cc [ v] = self . num_cc ;
69
63
if v == u { break ; }
70
64
}
71
65
}
72
66
}
73
67
68
+ // From the directed implication graph corresponding to a 2-SAT clause,
69
+ // finds a satisfying assignment if it exists or returns None otherwise.
74
70
pub fn two_sat_assign ( & self ) -> Option < Vec < bool > > {
75
71
( 0 ..self . graph . num_v ( ) /2 ) . map ( |i| {
76
- let scc_true = self . vdata [ 2 * i] . cc ;
77
- let scc_false = self . vdata [ 2 * i+1 ] . cc ;
72
+ let scc_true = self . cc [ 2 * i] ;
73
+ let scc_false = self . cc [ 2 * i+1 ] ;
78
74
if scc_true == scc_false { None } else { Some ( scc_true < scc_false) }
79
75
} ) . collect ( )
80
76
}
81
77
78
+ // Gets the vertices of a directed acyclic graph (DAG) in topological order.
79
+ pub fn topological_sort ( & self ) -> Vec < usize > {
80
+ let mut vertices = ( 0 ..self . graph . num_v ( ) ) . collect :: < Vec < _ > > ( ) ;
81
+ vertices. sort_by_key ( |& u| self . num_cc - self . cc [ u] ) ;
82
+ vertices
83
+ }
84
+
82
85
// Biconnected components are a work in progress.
83
- fn bcc ( & mut self , u : usize , par : usize ) {
84
- self . t += 1 ;
85
- self . vdata [ u] . low = self . t ;
86
- self . vdata [ u] . vis = self . t ;
87
- self . verts . push ( u) ;
86
+ fn bcc ( & mut self , u : usize , par : usize , t : & mut usize , vis : & mut [ usize ] ,
87
+ low : & mut [ usize ] , verts : & mut Vec < usize > , edges : & mut Vec < usize > ) {
88
+ * t += 1 ;
89
+ vis[ u] = * t;
90
+ low[ u] = * t;
91
+ verts. push ( u) ;
88
92
for ( e, v) in self . graph . adj_list ( u) {
89
- if self . vdata [ v] . vis == 0 {
90
- self . edges . push ( e) ;
91
- self . bcc ( v, e) ;
92
- self . vdata [ u] . low = min ( self . vdata [ u] . low , self . vdata [ v] . low ) ;
93
- if self . vdata [ u] . vis <= self . vdata [ v] . low { // u is a cut vertex unless it's a one-child root
94
- while let Some ( top_e) = self . edges . pop ( ) {
93
+ if vis[ v] == 0 {
94
+ edges. push ( e) ;
95
+ self . bcc ( v, e, t, vis, low, verts, edges) ;
96
+ low[ u] = min ( low[ u] , low[ v] ) ;
97
+ if vis[ u] <= low[ v] { // u is a cut vertex unless it's a one-child root
98
+ self . num_vcc += 1 ;
99
+ while let Some ( top_e) = edges. pop ( ) {
95
100
self . vcc [ top_e] = self . num_vcc ;
96
101
self . vcc [ top_e ^ 1 ] = self . num_vcc ;
97
102
if e ^ top_e <= 1 { break ; }
98
103
}
99
- self . num_vcc += 1 ;
100
104
}
101
105
}
102
- else if self . vdata [ v] . vis < self . vdata [ u] . vis && e != ( par^ 1 ) {
103
- self . vdata [ u] . low = min ( self . vdata [ u] . low , self . vdata [ v] . vis ) ;
104
- self . edges . push ( e) ;
106
+ else if vis [ v] < vis [ u] && e ^ par != 1 {
107
+ low [ u] = min ( low [ u] , vis [ v] ) ;
108
+ edges. push ( e) ;
105
109
}
106
110
else if v == u { // e is a self-loop
111
+ self . num_vcc += 1 ;
107
112
self . vcc [ e] = self . num_vcc ;
108
113
self . vcc [ e ^ 1 ] = self . num_vcc ;
109
- self . num_vcc += 1 ;
110
114
}
111
115
}
112
- if self . vdata [ u] . vis <= self . vdata [ u] . low { // par is a cut edge unless par==-1
113
- while let Some ( v) = self . verts . pop ( ) {
114
- self . vdata [ v] . cc = self . num_cc ;
116
+ if vis[ u] == low[ u] { // par is a cut edge unless par==-1
117
+ self . num_cc += 1 ;
118
+ while let Some ( v) = verts. pop ( ) {
119
+ self . cc [ v] = self . num_cc ;
115
120
if v == u { break ; }
116
- }
117
- self . num_cc += 1 ;
121
+ }
118
122
}
119
123
}
120
124
125
+ // In an undirected graph, determines whether u is an articulation vertex.
121
126
pub fn is_cut_vertex ( & self , u : usize ) -> bool {
122
127
if let Some ( first_e) = self . graph . first [ u] {
123
- self . graph . adj_list ( u) . any ( |( e, _) | { self . vcc [ e ] != self . vcc [ first_e ] } )
128
+ self . graph . adj_list ( u) . any ( |( e, _) | { self . vcc [ first_e ] != self . vcc [ e ] } )
124
129
}
125
130
else {
126
131
false
127
132
}
128
133
}
129
134
135
+ // In an undirected graph, determines whether v is a bridge
130
136
pub fn is_cut_edge ( & self , e : usize ) -> bool {
131
137
let u = self . graph . endp [ e ^ 1 ] ;
132
138
let v = self . graph . endp [ e] ;
133
- self . vdata [ u] . cc != self . vdata [ v] . cc
139
+ self . cc [ u] != self . cc [ v]
134
140
}
135
141
}
136
142
@@ -147,11 +153,11 @@ mod test {
147
153
graph. add_two_sat_clause ( x, z) ;
148
154
graph. add_two_sat_clause ( y^1 , z^1 ) ;
149
155
graph. add_two_sat_clause ( y, y) ;
150
- assert_eq ! ( CCGraph :: new( & graph, true ) . two_sat_assign( ) ,
156
+ assert_eq ! ( ConnectivityGraph :: new( & graph, true ) . two_sat_assign( ) ,
151
157
Some ( vec![ true , true , false ] ) ) ;
152
158
153
159
graph. add_two_sat_clause ( z, z) ;
154
- assert_eq ! ( CCGraph :: new( & graph, true ) . two_sat_assign( ) , None ) ;
160
+ assert_eq ! ( ConnectivityGraph :: new( & graph, true ) . two_sat_assign( ) , None ) ;
155
161
}
156
162
157
163
#[ test]
@@ -162,7 +168,7 @@ mod test {
162
168
graph. add_undirected_edge ( 1 , 2 ) ;
163
169
graph. add_undirected_edge ( 1 , 2 ) ;
164
170
165
- let cc_graph = CCGraph :: new ( & graph, false ) ;
171
+ let cc_graph = ConnectivityGraph :: new ( & graph, false ) ;
166
172
let bridges = ( 0 ..graph. num_e ( ) ) . filter ( |& e| cc_graph. is_cut_edge ( e) ) . collect :: < Vec < _ > > ( ) ;
167
173
let articulation_points = ( 0 ..graph. num_v ( ) ) . filter ( |& u| cc_graph. is_cut_vertex ( u) ) . collect :: < Vec < _ > > ( ) ;
168
174
assert_eq ! ( bridges, vec![ 0 , 1 ] ) ;
0 commit comments