알고리즘/백준 BAEK JOON
1260. DFS와 BFS ( Stack & Queue 사용 )
IMyoungho
2020. 3. 10. 01:25
이번에 풀어볼 문제는 백준 1260번 이며 완전탐색 알고리즘의 대표 DFS와 BFS이다.
# 많은 블로그에서 해당 알고리즘에 대한 자세한 설명이 되어있으니 참고!!
나의 경우는 DFS의 경우 재귀함수를 사용해서 풀어도 되지만 굳이 Stack을 너무나 사용해서 풀고 싶었다.
알고리즘을 다시 시작한지 얼마안되서 꽤 오랜시간이 걸렸지만 그래도 해내서 다행이다:)
Stack과 Queue에 대한 개념과 DFS와 BFS의 탐색 과정을 생각하며 구현하면된다!
-> 구현을 외우는 것이 아니라 이해하는 것이 중요하고 예외처리를 잘 하는것이 가장 중요한 Point다!
< Code 설명 >
#include <iostream>
#include <stack>
#include <queue>
#define MAX 1001
using namespace std;
int n, m, v;
bool visit1[MAX];
bool visit2[MAX];
int arr[MAX][MAX];
//정점 개수 N, 간선 개수 M, 시작 정점 번호 V
void dfs(int v){
stack<int>s;
s.push(v);
visit1[v]=true;
cout << v << " ";
while(!s.empty()){ // Stack이 텅 빌때까지 진행!
for(int i=1; i<=n; i++){ // 시작정점부터 for문으로 순서대로 dfs탐색 진행
if(visit1[i]==false){ // 방문한 정점인지 Check
if(arr[v][i]==1){ // 정점사이에 간선이 존재하는지 Check
s.push(i); // 방문한 적이 없고 간선이 존재 -> 스택에 push
visit1[i]=true; // 방문한 정점은 True로 Check
v = s.top(); // 스택의 최상위를 기준정점으로 초기화해서 탐색
// -> 해당 정점과 연결된 정점 탐색을 위해
// -> 이런식으로 하면 정점 순서(낮은)대로 탐색가능
i=0; // 최상위 정점과 연결된 정점들과 간선 탐색
// 방문한 적이 없는 정점들 기준으로 간선이 있는지
// 최상위 정점과 연결된 간선이 있나 처음부터 탐색
// -> for문이므로 정점순서가 낮은 순서로 쌓이게됨
// -> for 문의 i++ 주의해서 구현!!
cout << v << ' '; // 스택 최상위 값 출력
}
}
}
// for 문이 끝났는 것 == 깊이 끝까지 탐색했다는 것, 이제 미탐색한 나머지를 찾아 방문
if(visit1[v]==true){ // 만약 방문한적이 있다면
s.pop(); // 스택에서 pop해준다.
// -> 더 이상 탐색을 할 필요가 없는 정점이므로..
// -> 더 이상 간선이 없으며 방문한적이 있는 경우
if(!s.empty()) // 스택이 비어있지 않다면
v = s.top(); // 거슬러 올라간 부분에서 재탐색하기위해
// v값을 스택의 최상위 값으로 저장
}
}
cout << endl;
}
void bfs(int v){
queue <int>q;
q.push(v);
visit2[v]=true;
cout << v << " ";
while(!q.empty()){ // Queue가 텅 빌때까지!
for(int i=1; i<=n; i++){ // 정점의 갯수만큼 반복한다.
if(visit2[i]==false && arr[v][i]==1){ // 방문한적 없고 간선이 있다면
q.push(i); // Queue에 넣는다.
visit2[i]=true; // 방문 Check
cout << i << " "; // 방문하자마자 출력한다!
}
}
if(visit2[v]==true){ // 제일 처음시작한 정점과 연결된
// 간선을 모두 방문했다면
q.pop(); // 그 정점을 빼고 다음의 빠른순서의
// 정점부터 재탐색한다.
v=q.front(); // Queue의 제일 앞에 있는 것이
// 다음으로 빠른순서의 정점이 된다.
// 그 이유는 for문을 참조
}
}
}
int main() {
cin >> n >> m >> v;
int st, ed;
for(int i=0; i<m; i++){
cin >> st >> ed;
arr[st][ed] = arr[ed][st] = 1;
}
dfs(v);
bfs(v);
return 0;
}
반드시 알아야할 TIP!!
# 항상 알고리즘을 짜기전에 히든 테스트 케이스를 염두해두고 스스로 설계할줄 알아야한다.
# 구현 후 : 히든 테스트케이스를 만들고 디버깅을 하면서 제대로 동작하는지 확인해야한다!
-> 히든 테스트 케이스가 시간을 단축시켜준다!!
# 그리고 되도록이면 Check할 배열은 bool형을 쓰자!! -> 디버깅할 때 편한거 같다.(개인차)
반응형