-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathArticulationandBridges.cpp
More file actions
141 lines (117 loc) · 3.21 KB
/
ArticulationandBridges.cpp
File metadata and controls
141 lines (117 loc) · 3.21 KB
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
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
typedef vector<int> VI;
typedef vector<VI> VVI;
typedef long long LL;
typedef map<int,int>::iterator ITmii;
#define EPS 1e-9
#define FOR1(x,y,z) for( int x = y; x < z ; ++x)
#define FOR(x,y) FOR1(x,0,y)
#define FOR2(x,y) for(int x = y; x >= 0; --x)
#define PB push_back
#define ALL(X) (X).begin(), (X).end()
#define SORT(X) sort(ALL(X))
#define SIZE(X) ((int)(X).size())
/*
* Given a undirected graph with n vertices and m edges
* we are asked to find:
* articulation points
* bridges
* Our algorithm will run in O(V+E)
*/
VI dfs_num; //when a vertex is visited for the first time
VI dfs_low; //stores the lowest value dfs_num reachable from the subtree
//VI articulation; //stores articulation points
VI parent;
VVI adj; //adjacency matrix
/*we can see that we will only update dfs_low to a lower value if there
*is a cycle (backtracks to an earlier value)
*/
/*
* given u,v neighbours
* if dfs_low(v) >= dfs_num(u)
* it means there is no backedge from v to a parent of u(cycle)
* to go its parent
* you must go through u, which makes it an articulation point
*/
//there is a special case if we start the dfs with an
//articulation point
/*
* given u,v neighbours
* if dfs_low(v) > dfs_num(u) then edge u,v is a bridge
* i.e. there is no dfs subtree from v that return to u
*/
int cnt = 0;
//int dfsroot;
//int rootchildren;
// this will count when we arrive in the dfs
//https://jutge.org/problems/P37339_en
//find bridges and print in ascending order
struct Edge{
int u;
int v;
//int weight;
bool operator< (const Edge& a) const{
if(a.u == u) return a.v < v;
return a.u < u;
}
//we can overload the operator to have a default less comparison
};
priority_queue<Edge> pq;
//-----
void dfs(int u){
dfs_num[u] = dfs_low[u] = cnt++;
for(int i = 0; i < adj[u].size(); ++i){
int v = adj[u][i];
//not visited
if( dfs_num[v] == -1){
parent[v] = u; //we assign its parent to avoid cycles a-b-a
dfs(v);
//if(u == dfsroot) rootchildren++; //special case it must have more than 1 children
//~ if(dfs_low[v] >= dfs_num[u]){
//~ articulation[u] = true;
//~ }
if(dfs_low[v] > dfs_num[u]){
pq.push({min(u,v),max(u,v)});
}
dfs_low[u] = min(dfs_low[u], dfs_low[v]);
}
//already visited => cycle
else if (v != parent[u]){ //cycle aba
dfs_low[u] = min(dfs_low[u], dfs_num[v]);
}
}
}
int main(){
int n,m;
while(cin >> n >> m){
cnt = 0;
adj = VVI(n);
dfs_low = dfs_num = parent = VI(n,-1);
//articulation = VI(n,0);
for(int i = 0; i < m; ++i){
int x,y;
cin >> x >> y;
adj[x].push_back(y);
adj[y].push_back(x);
}
for (int i = 0; i < n; ++i){
if (dfs_num[i] == -1) {
//dfsroot = i;
//rootchildren = 0;
dfs(i);
//articulation[dfsroot] = (rootchildren > 1);
}
}
//print
cout << pq.size() << endl;
while(!pq.empty()){
Edge e = pq.top(); pq.pop();
cout << e.u << ' ' << e.v;
if(!pq.empty()) cout << " ";
}
cout << endl << "----------" << endl;
}
}