-
Notifications
You must be signed in to change notification settings - Fork 0
/
ComputeSCC.cpp
202 lines (163 loc) · 3.72 KB
/
ComputeSCC.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
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <iterator>
#include <sstream>
#include <list>
#include <string>
#include <stack>
#include <vector>
#include <algorithm>
using namespace std;
vector<int> sccCount;
int sccSize;
class Graph
{
// Number of nodes
int n;
vector<int> *adj;
// Depth First Search
void DFS(int n, bool explored[]);
// Function to fill stack with nodes
void createStack(int n, bool explored[], stack<int> &Stack);
public:
Graph(int n);
void addEdge(int n, int w);
// Main function to run the SCC finding algorithm
void findSCCs();
// Function to transpose the graph for 2nd DFS
Graph Reverse();
};
Graph::Graph(int n)
{
this->n = n;
adj = new vector<int>[n];
}
// Depth First Search function
void Graph::DFS(int n, bool explored[])
{
// Current node is now explored
explored[n] = true;
// Recursive iterations for all nodes
vector<int>::iterator i;
for (i = adj[n].begin(); i != adj[n].end(); ++i)
if (!explored[*i])
{
DFS(*i, explored);
}
sccSize += 1;
}
//Function used to reverse the graph before 2nd DFS
Graph Graph::Reverse()
{
Graph g(n);
for (int j = 0; j < n; j++)
{
// Look at all adjacent nodes
vector<int>::iterator i;
for (i = adj[j].begin(); i != adj[j].end(); ++i)
{
g.adj[*i].push_back(j);
}
}
return g;
}
void Graph::addEdge(int n, int w)
{
adj[n].push_back(w);
}
void Graph::createStack(int n, bool explored[], stack<int> &Stack)
{
// Mark the current node as explored and print it
explored[n] = true;
// Recur for all the nodes adjacent to this node
vector<int>::iterator i;
for (i = adj[n].begin(); i != adj[n].end(); ++i)
if (!explored[*i])
createStack(*i, explored, Stack);
Stack.push(n);
}
// The main function that finds and prints all SCCs
void Graph::findSCCs()
{
stack<int> Stack;
// Mark all the nodes as unexplored
bool *explored = new bool[n];
for (int i = 0; i < n; i++)
explored[i] = false;
// Add nodes into stack
for (int i = 0; i < n; i++)
{
if (explored[i] == false)
createStack(i, explored, Stack);
}
// Create a reversed graph
Graph gReversed = Reverse();
// Mark all the nodes as unexplored
for (int i = 0; i < n; i++)
explored[i] = false;
// Process all nodes in the reverse order from the first DFS
while (Stack.empty() == false)
{
// Grab a node
int v = Stack.top();
Stack.pop();
// Add SCC size to vector
if (explored[v] == false)
{
sccSize = 0;
gReversed.DFS(v, explored);
sccCount.push_back(sccSize);
}
}
}
//Function used to split a string into a vector
vector<std::string> &split(const string &s, char delim, vector<string> &elems) {
stringstream ss(s);
string item;
while (getline(ss, item, delim)) {
elems.push_back(item);
}
return elems;
}
//Function used to split a string into a vector
vector<string> split(const string &s, char delim) {
vector<string> elems;
split(s, delim, elems);
return elems;
}
// Main function reads input from file and runs quicksort
int _tmain(int argc, _TCHAR* argv[])
{
ifstream file("C:/Users/sean/Downloads/test1.txt", ios::in);
string tmp;
int numNodes = 0;
numNodes = std::count(std::istreambuf_iterator<char>(file),
std::istreambuf_iterator<char>(), '\n') + 1;
file.clear();
file.seekg(0, ios::beg);
Graph g(numNodes);
//Read file into graph structure
while (!file.eof())
{
getline(file, tmp);
vector<string> splitLine = split(tmp, ' ');
if (splitLine.size() == 0)
continue;
for (int i = 1; i < (int)splitLine.size(); i++)
{
g.addEdge(stoi(splitLine[0]), stoi(splitLine[i]));
}
}
file.close();
cout << "Starting algorithm... \n";
g.findSCCs();
sort(sccCount.rbegin(), sccCount.rend());
cout << "Top 5 SCC's are: \n";
for (int i = 0; i < 5; i++)
{
cout << sccCount[i] << endl;;
}
getchar();
return 0;
}