정리충의 정리노트

[백준] 2668: 숫자고르기 본문

PS/BFS & DFS

[백준] 2668: 숫자고르기

ioqoo 2020. 1. 19. 03:50

0. 문제 주소

 

https://www.acmicpc.net/problem/2668

 

2668번: 숫자고르기

세로 두 줄, 가로로 N개의 칸으로 이루어진 표가 있다. 첫째 줄의 각 칸에는 정수 1, 2, …, N이 차례대로 들어 있고 둘째 줄의 각 칸에는 1이상 N이하인 정수가 들어 있다. 첫째 줄에서 숫자를 적절히 뽑으면, 그 뽑힌 정수들이 이루는 집합과, 뽑힌 정수들의 바로 밑의 둘째 줄에 들어있는 정수들이 이루는 집합이 일치한다. 이러한 조건을 만족시키도록 정수들을 뽑되, 최대로 많이 뽑는 방법을 찾는 프로그램을 작성하시오. 예를 들어, N=7인 경우 아래

www.acmicpc.net

 

 

1. 풀이

 

[PS] - [BOJ] 9466: 텀 프로젝트 랑 똑같은 문제.

 

윗줄에서 적절히 숫자들을 골랐을 때, 고른 숫자들에 대응되는 밑줄의 숫자들의 집합이 "윗줄에서 고른 숫자들의 집합"과 일치해야 한다.

 

정답이 1, 3, 5를 골랐을 때인데, 다음과 같이 생각하면 해답이 쉽게 떠오른다.

1. 윗줄에서 1을 고른다 -> 대응되는 밑줄의 숫자는 3이다.
2. 이번엔 1.에서 나온 밑줄의 숫자 3을 윗줄에서 고른다 -> 대응되는 밑줄의 숫자는 1이다.
3. 1은 이미 골랐던 숫자이다 : 사이클의 형태

[PS] - [BOJ] 9466: 텀 프로젝트 과 유사하다고 한 이유는, 모든 정점의 outdegree가 1인 그래프에서 사이클에 속한 정점의 개수를 찾는 상황이 정확히 똑같기 때문이다. 다만 9466번에선 개수만 구해야 했다면, 이 문제에선 그 사이클에 속한 정점 번호까지 요구하는 것이 다른 점이다.

 

 

2. 풀이 코드

 

* 유의할 점

 

 

#include <bits/stdc++.h>
#define MAX 105

using namespace std;

int N;
int E[MAX];
bool visited[MAX];
bool finished[MAX];
vector<int> ans;

void DFS(int curr){
    visited[curr] = true;
    int next = E[curr];
    if (visited[next]){
        if (!finished[next]){
            for (int start = next; start != curr; start = E[start]) {
                ans.push_back(start);
            }
            ans.push_back(curr);
        }
    }
    else DFS(next);

    finished[curr] = true;

}


int main(){
    #ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
    #endif // ONLINE_JUDGE

    scanf("%d", &N);
    for (int i=1;i<=N;i++){
        scanf("%d", &E[i]);
    }
    for (int i=1;i<=N;i++){
        if (!visited[i]) DFS(i);
    }
    sort(ans.begin(), ans.end());
    printf("%d\n", ans.size());
    for (int n: ans){
        printf("%d\n", n);
    }
}

 

 

 

'PS > BFS & DFS' 카테고리의 다른 글

[백준] 1039: 교환  (0) 2020.02.03
[백준] 3055: 탈출  (0) 2020.02.03
[백준] 9205: 맥주 마시면서 걸어가기  (0) 2020.01.19
[백준] 2146: 다리 만들기  (0) 2020.01.18
[백준] 9466: 텀 프로젝트  (0) 2020.01.18
Comments