1/*
2 * κ·Έλν κΈ°μ΄ (Graph Basics)
3 * Graph Representation, DFS, BFS, Connected Components
4 *
5 * κ·Έλνμ κΈ°λ³Έ ννκ³Ό νμ μκ³ λ¦¬μ¦μ
λλ€.
6 */
7
8#include <iostream>
9#include <vector>
10#include <queue>
11#include <stack>
12#include <unordered_set>
13#include <algorithm>
14
15using namespace std;
16
17// =============================================================================
18// 1. κ·Έλν νν
19// =============================================================================
20
21// μΈμ 리μ€νΈ
22class AdjacencyList {
23public:
24 int V;
25 vector<vector<int>> adj;
26 bool directed;
27
28 AdjacencyList(int v, bool dir = false) : V(v), adj(v), directed(dir) {}
29
30 void addEdge(int u, int v) {
31 adj[u].push_back(v);
32 if (!directed) {
33 adj[v].push_back(u);
34 }
35 }
36
37 void print() {
38 for (int i = 0; i < V; i++) {
39 cout << i << ": ";
40 for (int neighbor : adj[i]) {
41 cout << neighbor << " ";
42 }
43 cout << endl;
44 }
45 }
46};
47
48// μΈμ νλ ¬
49class AdjacencyMatrix {
50public:
51 int V;
52 vector<vector<int>> matrix;
53
54 AdjacencyMatrix(int v) : V(v), matrix(v, vector<int>(v, 0)) {}
55
56 void addEdge(int u, int v, int weight = 1) {
57 matrix[u][v] = weight;
58 matrix[v][u] = weight; // 무방ν₯
59 }
60
61 void print() {
62 for (int i = 0; i < V; i++) {
63 for (int j = 0; j < V; j++) {
64 cout << matrix[i][j] << " ";
65 }
66 cout << endl;
67 }
68 }
69};
70
71// =============================================================================
72// 2. DFS (κΉμ΄ μ°μ νμ)
73// =============================================================================
74
75void dfsRecursive(const vector<vector<int>>& adj, int node, vector<bool>& visited, vector<int>& result) {
76 visited[node] = true;
77 result.push_back(node);
78
79 for (int neighbor : adj[node]) {
80 if (!visited[neighbor]) {
81 dfsRecursive(adj, neighbor, visited, result);
82 }
83 }
84}
85
86vector<int> dfs(const vector<vector<int>>& adj, int start) {
87 int n = adj.size();
88 vector<bool> visited(n, false);
89 vector<int> result;
90 dfsRecursive(adj, start, visited, result);
91 return result;
92}
93
94// λ°λ³΅μ DFS
95vector<int> dfsIterative(const vector<vector<int>>& adj, int start) {
96 int n = adj.size();
97 vector<bool> visited(n, false);
98 vector<int> result;
99 stack<int> st;
100
101 st.push(start);
102
103 while (!st.empty()) {
104 int node = st.top();
105 st.pop();
106
107 if (visited[node]) continue;
108 visited[node] = true;
109 result.push_back(node);
110
111 for (auto it = adj[node].rbegin(); it != adj[node].rend(); ++it) {
112 if (!visited[*it]) {
113 st.push(*it);
114 }
115 }
116 }
117
118 return result;
119}
120
121// =============================================================================
122// 3. BFS (λλΉ μ°μ νμ)
123// =============================================================================
124
125vector<int> bfs(const vector<vector<int>>& adj, int start) {
126 int n = adj.size();
127 vector<bool> visited(n, false);
128 vector<int> result;
129 queue<int> q;
130
131 q.push(start);
132 visited[start] = true;
133
134 while (!q.empty()) {
135 int node = q.front();
136 q.pop();
137 result.push_back(node);
138
139 for (int neighbor : adj[node]) {
140 if (!visited[neighbor]) {
141 visited[neighbor] = true;
142 q.push(neighbor);
143 }
144 }
145 }
146
147 return result;
148}
149
150// BFS μ΅λ¨ 거리
151vector<int> bfsDistance(const vector<vector<int>>& adj, int start) {
152 int n = adj.size();
153 vector<int> dist(n, -1);
154 queue<int> q;
155
156 q.push(start);
157 dist[start] = 0;
158
159 while (!q.empty()) {
160 int node = q.front();
161 q.pop();
162
163 for (int neighbor : adj[node]) {
164 if (dist[neighbor] == -1) {
165 dist[neighbor] = dist[node] + 1;
166 q.push(neighbor);
167 }
168 }
169 }
170
171 return dist;
172}
173
174// =============================================================================
175// 4. μ°κ²° μμ
176// =============================================================================
177
178int countConnectedComponents(int n, const vector<vector<int>>& adj) {
179 vector<bool> visited(n, false);
180 int count = 0;
181
182 for (int i = 0; i < n; i++) {
183 if (!visited[i]) {
184 count++;
185 queue<int> q;
186 q.push(i);
187 visited[i] = true;
188
189 while (!q.empty()) {
190 int node = q.front();
191 q.pop();
192 for (int neighbor : adj[node]) {
193 if (!visited[neighbor]) {
194 visited[neighbor] = true;
195 q.push(neighbor);
196 }
197 }
198 }
199 }
200 }
201
202 return count;
203}
204
205// =============================================================================
206// 5. μ¬μ΄ν΄ νμ§
207// =============================================================================
208
209// 무방ν₯ κ·Έλν μ¬μ΄ν΄ νμ§ (DFS)
210bool hasCycleUndirected(const vector<vector<int>>& adj, int node, int parent, vector<bool>& visited) {
211 visited[node] = true;
212
213 for (int neighbor : adj[node]) {
214 if (!visited[neighbor]) {
215 if (hasCycleUndirected(adj, neighbor, node, visited)) {
216 return true;
217 }
218 } else if (neighbor != parent) {
219 return true;
220 }
221 }
222
223 return false;
224}
225
226bool detectCycleUndirected(int n, const vector<vector<int>>& adj) {
227 vector<bool> visited(n, false);
228
229 for (int i = 0; i < n; i++) {
230 if (!visited[i]) {
231 if (hasCycleUndirected(adj, i, -1, visited)) {
232 return true;
233 }
234 }
235 }
236
237 return false;
238}
239
240// λ°©ν₯ κ·Έλν μ¬μ΄ν΄ νμ§ (DFS)
241bool hasCycleDirected(const vector<vector<int>>& adj, int node, vector<int>& color) {
242 color[node] = 1; // λ°©λ¬Έ μ€ (νμ)
243
244 for (int neighbor : adj[node]) {
245 if (color[neighbor] == 1) { // νμ¬ DFS κ²½λ‘μμ λ°κ²¬
246 return true;
247 }
248 if (color[neighbor] == 0 && hasCycleDirected(adj, neighbor, color)) {
249 return true;
250 }
251 }
252
253 color[node] = 2; // μλ£ (κ²μμ)
254 return false;
255}
256
257bool detectCycleDirected(int n, const vector<vector<int>>& adj) {
258 vector<int> color(n, 0); // 0: λ―Έλ°©λ¬Έ, 1: λ°©λ¬Έ μ€, 2: μλ£
259
260 for (int i = 0; i < n; i++) {
261 if (color[i] == 0 && hasCycleDirected(adj, i, color)) {
262 return true;
263 }
264 }
265
266 return false;
267}
268
269// =============================================================================
270// 6. μ΄λΆ κ·Έλν κ²μ¬
271// =============================================================================
272
273bool isBipartite(const vector<vector<int>>& adj) {
274 int n = adj.size();
275 vector<int> color(n, -1);
276
277 for (int start = 0; start < n; start++) {
278 if (color[start] != -1) continue;
279
280 queue<int> q;
281 q.push(start);
282 color[start] = 0;
283
284 while (!q.empty()) {
285 int node = q.front();
286 q.pop();
287
288 for (int neighbor : adj[node]) {
289 if (color[neighbor] == -1) {
290 color[neighbor] = 1 - color[node];
291 q.push(neighbor);
292 } else if (color[neighbor] == color[node]) {
293 return false;
294 }
295 }
296 }
297 }
298
299 return true;
300}
301
302// =============================================================================
303// ν
μ€νΈ
304// =============================================================================
305
306void printVector(const vector<int>& v) {
307 cout << "[";
308 for (size_t i = 0; i < v.size(); i++) {
309 cout << v[i];
310 if (i < v.size() - 1) cout << ", ";
311 }
312 cout << "]";
313}
314
315int main() {
316 cout << "============================================================" << endl;
317 cout << "κ·Έλν κΈ°μ΄ μμ " << endl;
318 cout << "============================================================" << endl;
319
320 // ν
μ€νΈ κ·Έλν μμ±
321 // 0 --- 1
322 // | |
323 // 2 --- 3
324 // |
325 // 4
326 int n = 5;
327 vector<vector<int>> adj(n);
328 adj[0] = {1, 2};
329 adj[1] = {0, 3};
330 adj[2] = {0, 3};
331 adj[3] = {1, 2, 4};
332 adj[4] = {3};
333
334 // 1. DFS
335 cout << "\n[1] DFS (κΉμ΄ μ°μ νμ)" << endl;
336 auto dfsResult = dfs(adj, 0);
337 cout << " 0μμ μμ: ";
338 printVector(dfsResult);
339 cout << endl;
340
341 // 2. BFS
342 cout << "\n[2] BFS (λλΉ μ°μ νμ)" << endl;
343 auto bfsResult = bfs(adj, 0);
344 cout << " 0μμ μμ: ";
345 printVector(bfsResult);
346 cout << endl;
347
348 auto distances = bfsDistance(adj, 0);
349 cout << " 0μμ κ° λ
ΈλκΉμ§ 거리: ";
350 printVector(distances);
351 cout << endl;
352
353 // 3. μ°κ²° μμ
354 cout << "\n[3] μ°κ²° μμ" << endl;
355 vector<vector<int>> disconnected(6);
356 disconnected[0] = {1};
357 disconnected[1] = {0};
358 disconnected[2] = {3};
359 disconnected[3] = {2};
360 disconnected[4] = {5};
361 disconnected[5] = {4};
362 cout << " μ°κ²° μμ κ°μ: " << countConnectedComponents(6, disconnected) << endl;
363
364 // 4. μ¬μ΄ν΄ νμ§
365 cout << "\n[4] μ¬μ΄ν΄ νμ§" << endl;
366 cout << " 무방ν₯ κ·Έλν μ¬μ΄ν΄: " << (detectCycleUndirected(n, adj) ? "μμ" : "μμ") << endl;
367
368 vector<vector<int>> directedAdj(4);
369 directedAdj[0] = {1};
370 directedAdj[1] = {2};
371 directedAdj[2] = {3};
372 directedAdj[3] = {1}; // μ¬μ΄ν΄
373 cout << " λ°©ν₯ κ·Έλν μ¬μ΄ν΄: " << (detectCycleDirected(4, directedAdj) ? "μμ" : "μμ") << endl;
374
375 // 5. μ΄λΆ κ·Έλν
376 cout << "\n[5] μ΄λΆ κ·Έλν" << endl;
377 cout << " νμ¬ κ·Έλν: " << (isBipartite(adj) ? "μ΄λΆ κ·Έλν" : "μ΄λΆ κ·Έλν μλ") << endl;
378
379 // 6. 볡μ‘λ μμ½
380 cout << "\n[6] 볡μ‘λ μμ½" << endl;
381 cout << " | μκ³ λ¦¬μ¦ | μκ°λ³΅μ‘λ | 곡κ°λ³΅μ‘λ |" << endl;
382 cout << " |-----------------|------------|------------|" << endl;
383 cout << " | DFS | O(V + E) | O(V) |" << endl;
384 cout << " | BFS | O(V + E) | O(V) |" << endl;
385 cout << " | μ°κ²° μμ | O(V + E) | O(V) |" << endl;
386 cout << " | μ¬μ΄ν΄ νμ§ | O(V + E) | O(V) |" << endl;
387
388 cout << "\n============================================================" << endl;
389
390 return 0;
391}