리뷰
https://www.acmicpc.net/problem/4803
싸이클이 발생했다는 것에 대한 재정의를 하게 된 문제
전역 변수
- n : 노드의 개수를 저장할 변수
- m : 간선의 개수를 저장할 변수
- ans : 트리의 개수를 저장할 변수
- v : 각 노드의 방문 처리를 하기 위한 정수형 배열
함수
1. bfs
bool bfs(int sn, const vector<vector<int>>& lst)
너비 우선 탐색을 통해 싸이클 존재 여부를 판단하기 위한 함수
- 매개 변수로 시작 노드와 인접 리스트를 전달 받는다.
- 정수형 타입 큐 q를 초기화 하고 시작 노드를 큐에 삽입해 준다.
- 시작 노드를 1로 방문처리 해주고, 트리 여부를 판단할 bool 형식의 변수 isTree를 true로 초기화 한다.
- 큐가 빌 때 까지 탐색을 진행하고 큐의 제일 앞에 있는 노드를 꺼내 cn으로 초기화 한다.
- cn의 인접 리스트를 순회하며 각 노드에 대한 방문 처리를 진행하고 큐에 삽입해 준다.
- 만약 이미 방문한 노드일 경우 해당 노드가 cn의 부모 노드가 아니라면 isTree를 false로 변경해 준다.
- 모든 탐색을 마치고 최종적으로 isTree의 값을 리턴해 준다.
2. solve
void solve()
간선 정보를 입력 받아 인접 리스트를 초기화 하고 모든 노드를 탐색하는 함수
- 정수형 2차 벡터 lst를 n + 1크기로 초기화 해준다.
- m개의 간선 정보를 입력 받아 양방향 간선으로 추가해 준다.
- ans를 0으로 초기화 하고 n개의 노드를 순회한다.
- 만약 해당 노드가 이미 방문처리 되어 있다면 continue 처리해 준다.
- 만약 방문하지 않았따면 bfs를 수행하고, 리턴 값이 true라면 ans를 증가시켜 준다.
문제풀이
- 정답을 저장하고 출력하기 위한 문자열 벡터 result를 초기화 해준다.
- 정답 출력 시 각 케이스를 인덱싱 하기 위한 정수형 변수 cases를 0으로 초기화 해준다.
- cases를 전위 증가 시키고 무한 루프를 실행해 준다.
- n, m값을 입력 받고 만약 둘 다 0일 경우 break 처리하여 반복문을 빠져 나온다.
- memset 메서드를 통해 이전 케이스에서 사용한 방문 배열을 0으로 초기화 해준다.
- solve 함수를 통해 모든 노드를 탐색하며 트리의 개수를 ans에 저장해 준다.
- 문자열 temp에 ans의 개수에 따라 현재 케이스의 정답을 저장해 준다.
- result벡터에 temp를 추가해 준다.
- 반복문이 끝났을 경우 result에 저장된 문자열을 출력해 준다.
참고 사항
간선을 양방향으로 추가하였으므로, 방문한 노드를 만났을 때 부모 자식 관계인지 체크가 필요하다.
정답 코드
#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<string>
using namespace std;
int n, m, ans;
int v[501];
bool bfs(int sn, const vector<vector<int>>& lst) {
queue<int> q;
q.push(sn);
v[sn] = 1;
bool isTree = true;
while (!q.empty()) {
int cn = q.front(); q.pop();
for (int nn : lst[cn]) {
if (v[nn]) {
if (v[nn] != v[cn] - 1) isTree = false;
continue;
}
v[nn] = v[cn] + 1;
q.push(nn);
}
}
return isTree;
}
void solve() {
vector<vector<int>> lst(n + 1);
while (m--) {
int par, child; cin >> par >> child;
lst[par].push_back(child);
lst[child].push_back(par);
}
ans = 0;
for (int i = 1; i <= n; ++i) {
if (v[i]) continue;
if (bfs(i, lst)) ans++;
}
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
vector<string> result;
int cases = 0;
while (++cases) {
cin >> n >> m;
if (!n && !m) break;
memset(v, 0, sizeof(v));
solve();
string temp = "Case " + to_string(cases) + ": ";
if (ans > 1) temp += "A forest of " + to_string(ans) + " trees.\n";
else if (ans == 1) temp += "There is one tree.\n";
else temp += "No trees.\n";
result.push_back(temp);
}
for (const string& r : result) cout << r;
}
728x90
'알고리즘 공부 > C++' 카테고리의 다른 글
[S2] 백준 14713번 앵무새 C++ 해시맵, 문자열 (0) | 2024.11.25 |
---|---|
[G5] 백준 2504번 괄호의 값 C++ 스택 (1) | 2024.11.24 |
[G4] 백준 1339번 단어 수학 C++ 그리디 알고리즘, 우선순위 큐, 해시맵, 문자열 (0) | 2024.11.22 |
[G5] 백준 1240번 노드사이의 거리 C++ LCA, 트리 (0) | 2024.11.21 |
[G5] 백준 2470번 두 용액 C++ 투 포인터, 정렬 (0) | 2024.11.20 |