Skip to content

Commit

Permalink
Working articulation point calculator
Browse files Browse the repository at this point in the history
  • Loading branch information
jakedcolbert committed May 11, 2022
1 parent 574c828 commit 740b7ff
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 126 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@
- **Requirement 3 : Upgrading**

> minSpan() method implemented to find ideal connections for faster traversals and output recomendations to the terminal. Passes all tests with no diff issues and correct stylings. Completed by Elijah Opoku-Nyarko with later revisions by Jake Colbert.
> minSpan() method implemented to find ideal connections for faster traversals and output recomendations to the terminal. Passes most tests with occasional error and correct stylings. Completed by Elijah Opoku-Nyarko with later revisions by Jake Colbert.
- **Requirement 4 : Worst-Case Analysis of Bridge Collapse**

> removeBridges() method implemented to find towns that would form isolated groups on bridge collapse. Passes all tests with some diff issues regarding ordering and correct stylings. Completed by Elijah Opoku-Nyarko with output revisions by Jake Colbert.
- **Requirement 5 : Articulation Points**

> articulationPoints() method implemented to find points of the graph at which their destruction would disconnect the province graph. Does not pass tests. isAP[] array does not get modified by the recursive method and prints all zeros as it was initialized. In-Progress by Jake Colbert
> articulationPoints() method implemented to find points of the graph at which their destruction would disconnect the province graph. Passes all tests with no diff issues and correct stylings. Completed by Jake Colbert.
### Makefile & Testing

Expand Down
145 changes: 38 additions & 107 deletions province.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

#include <algorithm>
#include <string>
#include <vector>
#include <stack>
#include <cfloat>
#include <array>
Expand Down Expand Up @@ -272,9 +273,7 @@ void Province::minSpan(std::ostream & output) const {
std::vector<int> Province::bfs(int start) const {
// Initialize list of towns scheduled to visit
bool scheduled[_numberOfTowns];
for (int i = 0; i < _numberOfTowns; i ++) {
scheduled[i] = false;
}
memset(scheduled, 0, sizeof scheduled); // initialize to 0/false

// Initialize list of towns to visit with starting town
std::queue<int> toVisit;
Expand Down Expand Up @@ -306,10 +305,6 @@ std::vector<int> Province::bfs(int start) const {
return results;
}

void ap(int dfsTree[]) {

}

/**
* Remove bridges and print the list of towns that remain connected
*/
Expand Down Expand Up @@ -357,114 +352,50 @@ void Province::removeBridges(ostream &output) const {
}
}

void Province::dfs(vector<int> & dfsTowns) const {
stack<int> toExplore;
int town = 0;
bool visited[_numberOfTowns];
memset(visited, false, sizeof visited);
while(true) {
cerr << "while" << endl;
visited[town] = true;
cerr << "town " << _towns[town]._name << " is " << visited[town] << endl;
// find an unvisited road and continue while loop
for (std::list<Road>::const_iterator it = _towns[town]._roads.begin(); it != _towns[town]._roads.end(); it++) {
cerr << _towns[town]._name << "'s " << _towns[it->_head]._name << " " << _towns[it->_tail]._name << " " << _towns[town]._roads.size() << endl;
if (!visited[it->_head]) {
cerr << "New visit" << endl;
toExplore.push(town);
dfsTowns.push_back(town);
town = it->_head;
break;
}
}
if (toExplore.empty()) {
cerr << "empty" << endl;
break;


void Province::dfs(int v, bool visited[], int low[], int tin[], int & timer, std::vector<int> & ap, int p = -1) {
visited[v] = true;
tin[v] = low[v] = timer++;
int children=0;
for (Road to : _towns[v]._roads) {
if (to._tail == p) continue;
if (visited[to._head]) {
low[v] = min(low[v], tin[to._head]);
} else {
cerr << "leaf" << endl;
town = toExplore.top();
toExplore.pop();
dfs(to._head, visited, low, tin, timer, ap, v);
low[v] = min(low[v], low[to._head]);
if (low[to._head] >= tin[v] && p!=-1) {
ap.push_back(v);
}
++children;
}
}
for(std::vector<int>::iterator it = std::begin(dfsTowns); it != std::end(dfsTowns); ++it) {
std::cout << *it << "\n";
if (p == -1 && children > 1) {
ap.push_back(v);
}
}

void Province::APUtil(int u, bool visited[],
int disc[], int low[], int& time, int parent,
bool isAP[]) const {
// Count of children in DFS Tree
int children = 0;

// Mark the current node as visited
visited[u] = true;

// Initialize discovery time and low value
disc[u] = low[u] = ++time;

// Go through all vertices adjacent to this
for (int v = 0; v < _numberOfTowns; v++) {
// If v is not visited yet, then make it a child of u
// in DFS tree and recur for it
if (!visited[v]) {
children++;
APUtil(v, visited, disc, low, time, u, isAP);

// Check if the subtree rooted with v has
// a connection to one of the ancestors of u
low[u] = min(low[u], low[v]);

// If u is not root and low value of one of
// its child is more than discovery value of u.
if (parent != -1 && low[v] >= disc[u]) {
isAP[u] = true;
}
} else if (v != parent) {
low[u] = min(low[u], disc[v]);
}
void Province::articulationPoints(std::ostream & output) {
std::vector<int> ap;
bool visited[_numberOfTowns]; memset(visited, 0, sizeof visited);
int tin[_numberOfTowns]; memset(tin, 0, sizeof tin);
int low[_numberOfTowns]; memset(low, 0, sizeof low);
int timer = 0;
for (int i = 0; i < _numberOfTowns; ++i) {
if (!visited[i]) {
dfs(i, visited, low, tin, timer, ap);
}
}

// If u is root of DFS tree and has two or more children.
if (parent == -1 && children > 1) {
isAP[u] = true;
}
}

void Province::articulationPoints(std::ostream & output) const
{
output << "Destruction of any of the following would result in the province becoming\ndisconnected:" << endl;

int disc[_numberOfTowns];
memset(disc, 0, sizeof disc);
int low[_numberOfTowns];
bool visited[_numberOfTowns];
memset(visited, false, sizeof visited);
bool isAP[_numberOfTowns];
memset(isAP, false, sizeof isAP);
int time = 0, par = -1;
vector<int> towns;
dfs(towns);

// Adding this loop so that the
// code works even if we are given
// disconnected graph
for (int u = 0; u < _numberOfTowns; u++) {
if (!visited[u]) {
APUtil(u, visited, disc, low, time, par, isAP);
}
}
output << "Destruction of any of the following would result in the province becoming" << endl << "disconnected:" << endl;
int count = 0;

// Printing the APs
for (int u = 0; u < _numberOfTowns; u++) {
if (isAP[u] == true) {
output << " " << _towns[u]._name << endl;
count++;
}
}
if (count == 0) {
output << " (None)" << endl;
int apCount = 0;
for (int i : ap) {
output << " " << _towns[i]._name << endl;
apCount++;
}

if (apCount == 0) { output << " (None)" << endl; }

output << endl;
}
20 changes: 3 additions & 17 deletions province.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <string>
#include <list>
#include <map>
#include <vector>
#include <queue>

class Province {
Expand Down Expand Up @@ -61,37 +62,22 @@ class Province {
*
* @param output Stream to print data to
*/
void articulationPoints(std::ostream & output) const;
void articulationPoints(std::ostream & output);

~Province() {}

private:

int smallest(double dist [], std::list <int> toVisit, int numTowns) const;

void dfs(std::vector<int> & dfsTowns) const;
void dfs(int v, bool visited[], int low[], int tin[], int & timer, std::vector<int> & ap, int p);
/**
* Conduct a breadth-first traversal on the province, ignoring bridges
* @param start Index of town to start traversal at
* @return - List of indices of towns in order of traversal
*/
std::vector<int> bfs(int start) const;

/**
* Recursive helper for articulationPoints()
*
* @param u
* @param visited
* @param disc
* @param low
* @param time
* @param parent
* @param isAP
*/
void APUtil(int u, bool visited[],
int disc[], int low[], int& time, int parent,
bool isAP[]) const;

/**
* Road
* Contains index of originating town, whether or not is bridge,
Expand Down

0 comments on commit 740b7ff

Please sign in to comment.