-
Notifications
You must be signed in to change notification settings - Fork 308
/
biconnected_components.cpp
169 lines (146 loc) · 4.81 KB
/
biconnected_components.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
// https://practice.geeksforgeeks.org/problems/biconnected-graph/0
// C++ code to find the biconnected components in a graph
// as soon as a articulation point is found
// the no. of edges in the stack (stored edges discovered)
// are popped till the top edge is same as that which discovered the AP
#include <bits/stdc++.h>
using namespace std;
const int MAX = 100;
int adj_matrix[MAX][MAX];
vector <bool> visited(MAX, 0);
vector <int> discovery_time(MAX, 0);
vector <int> low_time(MAX, 0);
vector <int> AP(MAX, 0);
vector <int> parent(MAX, -1);
// store the edges in each biconnected component
vector <vector <pair <int, int> > > biconnected_components;
// store the edges in the stack
stack <pair <int, int> > component_edges;
/* dfs function for finding biconnected components
V = number of vertices
source = source vertex
time = visiting time
calculates the vectors discovery_time, low_time & AP */
void dfs_AP(int V, int source, int time) {
visited[source] = 1;
discovery_time[source] = low_time[source] = time;
int num_children = 0;
for (int v = 0; v < V; v ++) {
if (adj_matrix[source][v] == 1) {
if (!visited[v]) {
num_children ++;
parent[v] = source;
// push the edge source->v onto the stack
component_edges.push({source, v});
dfs_AP(V, v, time + 1);
low_time[source] = min(low_time[source], low_time[v]);
bool AP_found = false;
if (parent[source] == -1 && num_children > 1) {
// root having more than two distinct children
AP[source] = 1;
cerr << source << endl;
// AP detected
AP_found = true;
}
if (parent[source] != -1 && low_time[v] >= discovery_time[source]) {
// source has a child 'v' such that no vertex in the subtree
// rooted at 'v' has a back edge to one of the ancestors of source
// so, source is an articulation point
AP[source] = 1;
AP_found = true;
}
if (AP_found) {
// pop and store all edges in the current component
// from the stack till the edge source->v is found
// those edges including source->v forms one BCC
vector <pair <int, int> > current_component;
pair <int, int> edge = {source, v};
while (component_edges.top() != edge) {
current_component.push_back(component_edges.top());
component_edges.pop();
}
// edges {source -> v}
current_component.push_back(component_edges.top());
biconnected_components.push_back(current_component);
component_edges.pop();
}
}
else if (parent[source] != v) {
// back edge
low_time[source] = min(low_time[source], discovery_time[v]);
}
}
}
}
/* function to find the articulation points in the given graph
stored in adj_matrix[][MAX]
V = number of vertices
considering the general case when graph can be disconnected */
void findBCC(int V) {
// V vertices, source = 0, time = 1
for (int i = 0; i < V; i ++) {
if (!visited[i]) {
dfs_AP(V, i, 1);
// may happen that the stack component_edges is not empty
vector <pair <int, int> > current_component;
while (!component_edges.empty()) {
current_component.push_back(component_edges.top());
component_edges.pop();
}
biconnected_components.push_back(current_component);
}
}
}
int main () {
#ifndef ONLINE_JUDGE
freopen("/Users/sahilbansal/Desktop/input.txt", "r", stdin);
freopen("/Users/sahilbansal/Desktop/output.txt", "w", stdout);
freopen("/Users/sahilbansal/Desktop/error.txt", "w", stderr);
#endif
int num_vertices, num_edges;
cin >> num_vertices >> num_edges;
// clear the adj_matrix
memset(adj_matrix, 0, sizeof(adj_matrix));
int vertex_u, vertex_v;
for (int i = 0; i < num_edges; i ++) {
cin >> vertex_u >> vertex_v;
adj_matrix[vertex_u][vertex_v] = 1;
adj_matrix[vertex_v][vertex_u] = 1;
}
// find the biconnected components
findBCC(num_vertices);
// print the biconnected components
/*
int num_BCC = biconnected_components.size();
cerr << "No. of BCC: " << num_BCC << endl;
for (int i = 0; i < num_BCC; i ++) {
cerr << "BCC " << i + 1 << endl;
for (int j = 0; j < biconnected_components[i].size(); j ++) {
cerr << biconnected_components[i][j].first << " " << biconnected_components[i][j].second << endl;
}
}
//*/
// print the no. of BCC's with even and odd vertices
// odd vertices => even edges in BCC
// even vertices => odd edges in BCC
int num_BCC = biconnected_components.size();
int odd_vertiecs_BCC = 0, even_vertices_BCC = 0;
for (int i = 0; i < num_BCC; i ++) {
if (biconnected_components[i].size() % 2 == 0) {
odd_vertiecs_BCC ++;
}
else {
even_vertices_BCC ++;
}
}
cout << odd_vertiecs_BCC << " " << even_vertices_BCC << endl;
// reinitialize vectors to 0
visited.assign(MAX, 0);
discovery_time.assign(MAX, 0);
low_time.assign(MAX, 0);
AP.assign(MAX, 0);
parent.assign(MAX, -1);
// clear the vectors
biconnected_components.clear();
return 0;
}