codeplus 백준 강사 강의 내용기반으로 정리한 내용입니다.(비공개 포스트)
그래프의 탐색
탐색 목적: 시작점 X 시작해서 모든 정점 1번씩 방문
DFS
DFS - 스택을 사용해서 최대한 가고 갈 수 없으면 이전 정점으로 돌아옴
한번씩 방문하기 위해 check 배열 필요
-> 재귀호출을 이용해서 구현
void dfs(int x) {
    check[x] = true;
    for(int i=1; i<=n; i++) {
        if (a[x][i] == 1 && check[i] == false) {
            dfs(i);
        }
    }
}
-> 인접행렬을 이용한 구현 (O(v^2))
void dfs(int x) {
    check[x] = true;
    for(int i=0; i<a[x].size(); i++) {
        int y = a[x][i];
        if (check[y] == false)
            dfs(y);
    }
}
-> 인접 리스트를 이용한 구현(O(v+e))
BFS
큐를 이용해서 모두 방문
-> 큐에 넣는 동시에 방문했다고 check 해주어야 함
queue<int> q;
check[1] = true; q.push(1);
while(!q.empty()) {
    in x = q.front(); q.pop();
    for(int i=1; i<=n; i++) {
        if (a[x][i] == 1 && check[i] == false) {
            check[i] = true;
            q.push(i);
        }
    }
}
-> 인접 행렬을 이용한 구현 (O(v^2))
queue<int> q;
check[1] = true; q.push(1);
while(!q.empty()) {
    in x = q.front(); q.pop();
    for(int i=0; i<a[x].size(); i++) {
        int y = a[x][i];
        if (check[y] == false) {
            check[y] = true; q.push(y);
        }
    }
}
-> 인접 리스트를 이용한 구현 (O(v+e))
DFS와 BFS 문제
#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
class DFS {
  int n;
  int v;
  vector<bool> check;
  vector<int> result;
public:
  DFS(int input_n, int start, vector<vector<int>>& graph) : n(input_n), v(start) {
    check.assign(input_n+1, false);
    result.push_back(start);
    dfs(start, graph);
  }
  void dfs(int x, vector<vector<int>>& graph) {
    check[x] = true;
    for (int i = 0; i<graph[x].size(); i++) {
      int y = graph[x][i];
      if (check[y] == false) {
        result.push_back(y);
        dfs(y, graph);
      }
    }
  }
  void print() {
    for (int i = 0; i < result.size(); ++i) {
      cout << result[i] << " ";
    }
    cout << endl;
  }
};
class BFS {
  int n;
  int v;
  vector<bool> check;
  vector<int> result;
public:
  BFS(int input_n, int start, vector<vector<int>>& graph) : n(input_n), v(start) {
    check.assign(input_n + 1, false);
    result.push_back(start);
    bfs(start, graph);
  }
  void bfs(int x, vector<vector<int>>& graph) {
    queue<int> q;
    q.push(x);
    check[x] = true;
    while (!q.empty()) {
      int y = q.front(); q.pop();
      for (int i = 0; i<graph[y].size(); i++) {
        int t = graph[y][i];
        if (check[t] == false) {
          check[t] = true;
          result.push_back(t);
          q.push(t);
        }
      }
    }
  }
  void print() {
    for (int i = 0; i < result.size(); ++i) {
      cout << result[i] << " ";
    }
    cout << endl;
  }
};
int main()
{
  int N = 0;
  int M = 0;
  int V = 0;
  cin >> N >> M >> V;
  vector<vector<int>> graph(N + 1, vector<int>(0, 0));
  for (int i = 0; i < M; ++i) {
    int a = 0;
    int b = 0;
    cin >> a >> b;
    graph[a].push_back(b);
    graph[b].push_back(a);
  }
  for (int i = 1; i <= N; ++i) {
    sort(graph[i].begin(), graph[i].end());
  }
  DFS dfs(N, V, graph);
  dfs.print();
  BFS bfs(N, V, graph);
  bfs.print();
  return 0;
}
---
> 연결요소
하나의 그래프이지만 각각 나누어진 그래프를 각각 연결요소라 부름
연결요소의 개수를 구하려면 BFS나 DFS를 이용해서 구할 수 있음
-> DFS, BFS의 목적이 한 정점에서 시작해서 여결된 모든 정점을 한번씩 방문하는 것이기 때문에 가능
#### 연결요소 문제
[연결요소 문제](https://www.acmicpc.net/problem/11724)
``` cpp
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
vector<bool> check;
class CC {
public:
  void operator()(int start, vector<vector<int>>& g) {
    bfs(start, g);
  }
  void bfs(int s, vector<vector<int>>& g) {
    queue<int> q;
    q.push(s);
    check[s] = true;
    while (!q.empty()) {
      int x = q.front(); q.pop();
      for (int i = 0; i < g[x].size(); ++i) {
        if (check[g[x][i]] == false) {
          check[g[x][i]] = true;
          q.push(g[x][i]);
        }
      }
    }
  }
};
int main()
{
  int N = 0;
  int M = 0;
  cin >> N >> M;
  check.assign(N + 1, false);
  vector<vector<int>> graph(N + 1, vector<int>(0, 0));
  for (int i = 0; i < M; ++i) {
    int a = 0;
    int b = 0;
    cin >> a >> b;
    graph[a].push_back(b);
    graph[b].push_back(a);
  }
  int result = 0;
  CC c;
  for (int i = 1; i <= N; ++i) {
    if (!check[i]) {
      result++;
      c(i, graph);
    }
  }
  cout << result << endl;
  return 0;
}
이분그래프
그래프를 A와 B로 나눌 수 있으면 이분 그래프라 함
A에 포함되어 있는 정점끼리 연결된 간선이 없음
B에 포함되어 있는 정점끼리 연결된 간선이 없음
모든 간선의 한 끝 점은 A에, 다른 끝 점은 B에
DFS 또는 BFS 탐색으로 이분그래프인지 아닌지 알 수 있다.
-> 방문한 적이 있는 정점에 대해 색을 검사해야함
이분그래프 문제
3-c 코드 -> 1이면 2가되고 2면 1이됨
#include <iostream>
#include <vector>
using namespace std;
class BipartiteGraph {
  vector<bool> check;
  vector<int> color;
  bool result = true;
public:
  void dfs(int start, int c, vector<vector<int>>& g) {
    check[start] = true;
    color[start] = c;
    for (int i = 0; i < g[start].size(); ++i) {
      if (color[g[start][i]] == 0) {
        if (check[g[start][i]] == false) {
            dfs(g[start][i], 3 - c, g);
        }
      }
      else if (color[start] == color[g[start][i]]) {
        result = false;
      }
    }
  }
  void operator()(int v, vector<vector<int>>& g) {
    check.assign(v+1, false);
    color.assign(v+1, 0);
    for (int i = 1; i <= v; ++i) {
      if (color[i] == 0)
        dfs(i, 1, g);
    }
    if (result)
      cout << "YES" << endl;
    else
      cout << "NO" << endl;
  }
};
int main()
{
  int testcase = 0;
  cin >> testcase;
  while (testcase--) {
    int V = 0;
    int E = 0;
    cin >> V >> E;
    vector<vector<int>> graph(V + 1, vector<int>(0, 0));
    for (int i = 0; i < E; ++i) {
      int a = 0;
      int b = 0;
      cin >> a >> b;
      graph[a].push_back(b);
      graph[b].push_back(a);
    }
    BipartiteGraph bg;
    bg(V, graph);
  }
  return 0;
}