2668번: 숫자고르기
세로 두 줄, 가로로 N개의 칸으로 이루어진 표가 있다. 첫째 줄의 각 칸에는 정수 1, 2, …, N이 차례대로 들어 있고 둘째 줄의 각 칸에는 1이상 N이하인 정수가 들어 있다. 첫째 줄에서 숫자를 적절
www.acmicpc.net
이 문제는 그래프 탐색, 깊이 우선 탐색 등으로 분류되어 있는데, 필자는 집합을 활용한 풀이를 생각했다.
첫 번째줄은 항상 1부터 N까지이고,
두 번째 줄에는 랜덤으로 숫자가 배치된다.
각 줄을 집합으로 묶어주고, 비교를 통해 같은지 판단하면 된다. 중요한 점은 항상 첫 번째 줄에는 모든 숫자가 등장하지만, 두 번째 줄에는 숫자들이 선택적으로 등장한다. 따라서 첫번째 줄을 순회하면서 두 번째 줄에 포함되는지 확인하고, 그렇지 않으면 제외하는 식으로 해결할 수 있다.
<주요 내용>
집합
<코드>
파이썬 버전
import sys si = sys.stdin.readline def main(): cards = {} n = int(si()) for i in range(1, n+1): cards[i] = int(si()) top = set(cards.keys()) bottom = set(cards.values()) while top != bottom: cnt = 0 for e in top: if e not in bottom: cnt += 1 del cards[e] top = set(cards.keys()) bottom = set(cards.values()) n -= cnt print(n) top = list(top) top.sort() for e in top: print(e) return if __name__ == '__main__': main()
C++ 버전
#include <iostream> #include <vector> #include <algorithm> #include <unordered_map> #define endl '\n' using namespace std; const int sz=1e2+1; int n,nmap[sz]; vector<int>v; unordered_map<int,int>umap; int main() { ios::sync_with_stdio(false); cin.tie(NULL);cout.tie(NULL); cin>>n; for(int i=1;i<=n;++i){ cin>>nmap[i]; v.push_back(i); if(umap.find(nmap[i])==umap.end()){ umap[nmap[i]]=1; }else umap[nmap[i]]++; } auto it=v.begin(); while(it!=v.end()){ auto e=v[it-v.begin()]; if(umap.find(e)==umap.end()){ v.erase(it); umap[nmap[e]]--; if(!umap[nmap[e]])umap.erase(nmap[e]); it=v.begin(); }else it++; } cout<<v.size()<<endl; sort(v.begin(),v.end()); for(auto e:v)cout<<e<<endl; return 0; }