Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
Tags
- 그리디
- 순열
- 피보나치 수
- 분할 정복
- 큐
- 링크드리스트
- 이분 탐색
- 비트마스크
- 문자열
- Knapsack
- MST
- SSAFY
- DP
- 메모리풀
- BeautifulSoup
- 재귀
- 완전 탐색
- 클래스
- 중복 순열
- BFS
- lis
- 크루스칼
- 우선순위 큐
- 세그먼트 트리
- 백트래킹
- dfs
- 조합
- 스택
- 시뮬레이션
- 빠른 입출력
Archives
- Today
- Total
작심 24/7
[백준] 9466번 텀 프로젝트 (C++) 본문
9466번: 텀 프로젝트
문제 이번 가을학기에 '문제 해결' 강의를 신청한 학생들은 텀 프로젝트를 수행해야 한다. 프로젝트 팀원 수에는 제한이 없다. 심지어 모든 학생들이 동일한 팀의 팀원인 경우와 같이 한 팀만
www.acmicpc.net
DFS로 풀 수 있는 문제이다.
팀이 구성되는 경우는 사이클이 생기는 경우라 생각하면 된다.
사이클이 생기는 경우를 찾아주기 위해 current와 visited 배열이 필요하다.
current엔 stack에 들어가 있는 애들을 표시해주고
visited는 비교가 끝난 애들을 체크해준다.
사이클이 생기는 경우엔 사이클의 시작과 끝을 담당하는 애를 leader에 넣어주고
current를 참고하여 사이클이 형성되는 부분까지는 팀이 구성되는 걸로 간주하여 카운트 값을 하나씩 줄여준다.
visited에도 표시를 해주어 더 이상 비교 대상에 들어가지 않게 한다.
사이클은 끝났는데 stack에 남아 있는 애들은 팀이 구성될 수 없기 때문에
전부 pop해주고 역시 visited도 표시해준다.
여기서 stack에 값을 push하기 전에 push할 값(top이 가리키고 있는 애)이 이미 visited된 상태라면
stack에 있는 애들은 팀을 구성할 수 없는 애들이므로
전부 pop해주고 visited에도 표시해준다.
#include <iostream>
#include <stack>
using namespace std;
int cnt;
void Dfs(int idx, int N, int student[], int visited[], int current[]) {
stack <int> st;
st.push(idx);
current[idx] = 1;
while (1) {
if (visited[student[st.top()]]) {
while (!st.empty()) {
current[st.top()] = 0;
visited[st.top()] = 1;
st.pop();
}
break;
}
st.push(student[st.top()]);
if (current[st.top()]) { //사이클이면
int leader = st.top();
if (visited[leader] == 0) {
visited[leader] = 1;
cnt--;
}
current[leader] = 0;
st.pop();
while (leader != st.top()) { //사이클이 형성되는 곳까진 팀이 구성 됨
cnt--;
visited[st.top()] = 1;
current[st.top()] = 0;
st.pop();
}
st.pop();
while (!st.empty()) { //그 외는 팀이 될 수 없음
visited[st.top()] = 1;
current[st.top()] = 0;
st.pop();
}
break;
}
else current[st.top()] = 1;
}
}
int main() {
int T, N;
cin >> T;
for (int t = 0; t < T; t++) {
int student[100001] = { 0 }, visited[100001] = { 0 }, current[100001] = { 0 };
cin >> N;
for (int n = 1; n <= N; n++) cin >> student[n];
cnt = N;
for (int i = 1; i <= N; i++) {
if (visited[i] == 0) Dfs(i, N, student, visited, current);
}
cout << cnt << "\n";
}
return 0;
}
원리는 이 영상을 참고했다.
여기서 설명하는 white set은 student 배열,
gray set은 current 배열,
black set은 visted 배열이다.
'백준' 카테고리의 다른 글
[백준] 1743번 음식물 피하기 (0) | 2020.06.09 |
---|---|
[백준] 11724번 연결 요소의 개수 (0) | 2020.06.09 |
[백준] 1012번 유기농 배추 (C++, JAVA) (0) | 2020.06.09 |
[백준] 1182번 부분수열의 합 (0) | 2020.06.08 |
[백준] 2503번 숫자 야구 (C++, JAVA) (0) | 2020.06.08 |
Comments