baekjoon

[백준] 2668 숫자고르기

윤만석 2023. 4. 20. 15:53

문제

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

이 경우에는 첫째 줄에서 1, 3, 5를 뽑는 것이 답이다. 첫째 줄의 1, 3, 5밑에는 각각 3, 1, 5가 있으며 두 집합은 일치한다. 이때 집합의 크기는 3이다. 만약 첫째 줄에서 1과 3을 뽑으면, 이들 바로 밑에는 정수 3과 1이 있으므로 두 집합이 일치한다. 그러나, 이 경우에 뽑힌 정수의 개수는 최대가 아니므로 답이 될 수 없다.

입력

첫째 줄에는 N(1≤N≤100)을 나타내는 정수 하나가 주어진다. 그 다음 줄부터는 표의 둘째 줄에 들어가는 정수들이 순서대로 한 줄에 하나씩 입력된다.

출력

첫째 줄에 뽑힌 정수들의 개수를 출력하고, 그 다음 줄부터는 뽑힌 정수들을 작은 수부터 큰 수의 순서로 한 줄에 하나씩 출력한다.

 

사이클이 있는지 확인하는 문제입니다.

한 정점이 그 저점 스스로를 가리키는 것도 사이클로 포함합니다.

 

타잔알고리즘을 사용해 응용하였습니다.

#include<bits/stdc++.h>
#define FAST ios_base::sync_with_stdio(false),cin.tie(NULL);
#define mset(v) memset(v,0,sizeof(v));
#define rep(i,a) for(int i=0;i<a;++i)
#define REP(i,a) for(int i=1;i<=a;++i)

using namespace std;

typedef long long ll;
typedef pair<int, int> pi;
typedef tuple<int, int, int>ti;
typedef vector<int> vi;
typedef vector<vector<int>> vvi;
int dy[] = { -1,0,1,0 }, dx[] = { 0,1,0,-1 }, INF = 987654321;

using namespace std;
int N, v[101], s[101], cnt, p[101], num, ans;
vi adj[101], st;
vvi cycle;
int dfs(int k) {
	st.push_back(k);
	int parent = v[k] = ++cnt;
	if (!v[p[k]]) {
		parent = min(parent, dfs(p[k]));
	}
	if (!s[p[k]]) {
		parent = min(parent, v[p[k]]);
	}
	if (parent == v[k]) {
		vi temp;
		while (1) {
			int t = st.back();
			temp.push_back(t);
			st.pop_back();
			s[t] = 1;
			if (t == k)break;
		}
		cycle.push_back(temp);
	}
	return parent;
}
int main() {
	FAST;
	cin >> N;
	REP(i, N) {
		cin >> p[i];
	}
	REP(i, N) {
		if (!v[i])dfs(i);
	}
	vi answer;
	for (vi temp : cycle) {
		if (temp.size() != 1) {
			for (int r : temp)answer.push_back(r);
		}
		else {
			if (temp[0] == p[temp[0]])answer.push_back(temp[0]);
		}
	}
	sort(answer.begin(), answer.end());
	cout << answer.size() << "\n";
	for (int r : answer)cout << r << "\n";
}

'baekjoon' 카테고리의 다른 글

[백준] 3184 양  (0) 2023.04.24
[백준]1595 북쪽나라의 도로  (1) 2023.04.20
[백준] 17831 대기업 승범이네  (0) 2023.04.19
[백준] 13398 연속합 2  (0) 2023.04.19
[백준] 1309 동물원  (0) 2023.04.19