Skip to content

Commit 85ce78d

Browse files
V0.1
1 parent 19e9b00 commit 85ce78d

File tree

11 files changed

+735084
-0
lines changed

11 files changed

+735084
-0
lines changed
+193
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
#include <string>
2+
#include <vector>
3+
#include <iostream>
4+
#include <set>
5+
#include <map>
6+
#include <stack>
7+
8+
template<typename T>
9+
struct Edge
10+
{
11+
size_t src;
12+
size_t dest;
13+
T weight;
14+
15+
// To compare edges, only compare their weights,
16+
// and not the source/destination vertices
17+
inline bool operator< (const Edge<T>& e) const
18+
{
19+
return this->weight < e.weight;
20+
}
21+
22+
inline bool operator> (const Edge<T>& e) const
23+
{
24+
return this->weight > e.weight;
25+
}
26+
};
27+
28+
template<typename T>
29+
class Graph
30+
{
31+
public:
32+
// Initialize the graph with N vertices
33+
Graph(size_t N) : V(N)
34+
{}
35+
36+
// Return number of vertices in the graph
37+
auto vertices() const
38+
{
39+
return V;
40+
}
41+
42+
// Return all edges in the graph
43+
auto& edges() const
44+
{
45+
return edge_list;
46+
}
47+
48+
void add_edge(Edge<T>& e)
49+
{
50+
// Check if the source and destination vertices are within range
51+
if (e.src >= 1 && e.src <= V &&
52+
e.dest >= 1 && e.dest <= V)
53+
edge_list.emplace_back(e);
54+
else
55+
std::cerr << "Vertex out of bounds" << std::endl;
56+
}
57+
58+
// Returns all outgoing edges from vertex v
59+
auto outgoing_edges(size_t v) const
60+
{
61+
std::vector<Edge<T>> edges_from_v;
62+
for (auto& e : edge_list)
63+
{
64+
if (e.src == v)
65+
edges_from_v.emplace_back(e);
66+
}
67+
return edges_from_v;
68+
}
69+
70+
// Overloads the << operator so a graph be written directly to a stream
71+
// Can be used as std::cout << obj << std::endl;
72+
template <typename T>
73+
friend std::ostream& operator<<(std::ostream& os, const Graph<T>& G);
74+
75+
private:
76+
size_t V; // Stores number of vertices in graph
77+
std::vector<Edge<T>> edge_list;
78+
};
79+
80+
template <typename T>
81+
std::ostream& operator<<(std::ostream& os, const Graph<T>& G)
82+
{
83+
for (auto i = 1; i < G.vertices(); i++)
84+
{
85+
os << i << ":\t";
86+
87+
auto edges = G.outgoing_edges(i);
88+
for (auto& e : edges)
89+
os << "{" << e.dest << ": " << e.weight << "}, ";
90+
91+
os << std::endl;
92+
}
93+
94+
return os;
95+
}
96+
97+
template <typename T>
98+
auto create_bipartite_reference_graph()
99+
{
100+
Graph<T> G(10);
101+
102+
std::map<unsigned, std::vector<std::pair<size_t, T>>> edges;
103+
edges[1] = { {2, 0} };
104+
edges[2] = { {1, 0}, {3, 0} , {8, 0} };
105+
edges[3] = { {2, 0}, {4, 0} };
106+
edges[4] = { {3, 0}, {6, 0} };
107+
edges[5] = { {7, 0}, {9, 0} };
108+
edges[6] = { {1, 0}, {4, 0} };
109+
edges[7] = { {5, 0} };
110+
edges[8] = { {2,0}, {9, 0} };
111+
edges[9] = { {5, 0} };
112+
113+
114+
for (auto& i : edges)
115+
for (auto& j : i.second)
116+
G.add_edge(Edge<T>{ i.first, j.first, j.second });
117+
118+
return G;
119+
}
120+
121+
template <typename T>
122+
auto bipartite_check(const Graph<T>& G)
123+
{
124+
std::stack<size_t> stack;
125+
std::set<size_t> visited;
126+
stack.push(1); // Assume that BFS always starts from vertex ID 1
127+
128+
enum class colors {NONE, RED, BLUE};
129+
colors current_color{colors::BLUE}; // This variable tracks the color to be assigned to the
130+
// next vertex that is visited.
131+
std::vector<colors> vertex_colors(G.vertices(), colors::NONE);
132+
133+
while (!stack.empty())
134+
{
135+
auto current_vertex = stack.top();
136+
stack.pop();
137+
138+
// If the current vertex hasn't been visited in the past
139+
if (visited.find(current_vertex) == visited.end())
140+
{
141+
visited.insert(current_vertex);
142+
vertex_colors[current_vertex] = current_color;
143+
if (current_color == colors::RED)
144+
{
145+
std::cout << "Coloring vertex " << current_vertex << " RED" << std::endl;
146+
current_color = colors::BLUE;
147+
}
148+
else
149+
{
150+
std::cout << "Coloring vertex " << current_vertex << " BLUE" << std::endl;
151+
current_color = colors::RED;
152+
}
153+
154+
// Add unvisited adjacent vertices to the stack.
155+
for (auto e : G.outgoing_edges(current_vertex))
156+
if (visited.find(e.dest) == visited.end())
157+
stack.push(e.dest);
158+
}
159+
// If the found vertex is already colored and
160+
// has a color same as its parent's color, the graph is not bipartite
161+
else if (visited.find(current_vertex) != visited.end() &&
162+
((vertex_colors[current_vertex] == colors::BLUE &&
163+
current_color == colors::RED) ||
164+
(vertex_colors[current_vertex] == colors::RED &&
165+
current_color == colors::BLUE)))
166+
return false;
167+
}
168+
169+
// If all vertices have been colored, the graph is bipartite
170+
return true;
171+
}
172+
173+
template <typename T>
174+
void test_bipartite()
175+
{
176+
// Create an instance of and print the graph
177+
auto BG = create_bipartite_reference_graph<T>();
178+
std::cout << BG << std::endl;
179+
180+
if (bipartite_check<T>(BG))
181+
std::cout << "The graph is bipartite" << std::endl;
182+
else
183+
std::cout << "The graph is not bipartite" << std::endl;
184+
}
185+
186+
int main()
187+
{
188+
using T = unsigned;
189+
test_bipartite<T>();
190+
191+
return 0;
192+
}
193+

Lesson06/Activity01/delete_this_file.txt

Whitespace-only changes.

0 commit comments

Comments
 (0)