문제 출처
1. 문제설명
N
개의 컴퓨터가 있다.
- A 컴퓨터가 B 컴퓨터를 신뢰하는 경우 B를 해킹하면,
- 즉
A->B
가 연결되었다는 의미로 해석된다.
2. 알고리즘 설계
- 그래프 + 탐색 문제 이다.
- 1번부터 돌면서 몇 개와 연결되어 있는지 탐색하면 된다.
- 그러나, 한번 탐색한 노드는 다시 탐색하지 않아야 한다.
3. 로직
- 값의 저장을 위해 2차원 벡터를 사용하였다.
- 처음 그래프 간선을 저장할 때 각 2차원 배열에 1차원 벡터로 연결을 표시하였다.
- 이후
DFS
를 돌면서 연결된 노드 수를 세면 된다.
- 이 때, 한 번 방문한 노드는 다시 갱신하지 않는다.
- 한 노드의 탐색이 끝나면
{개수, 노드 번호}
를 저장한다.
DFS
를 탐색이 끝나면 {개수, 노드 번호}
벡터를 정렬한다.
- 앞서 포스팅에서 언급했던 것처럼,
- 개수를 앞에 넣어 저장하면 별도의 operator를 만들지 않아도 된다.
- 개수가 같은 노드들을 출력한다.
4. 전체 코드
#include<bits/stdc++.h>
using namespace std;
using pii = pair<int, int>;
const int SZ = 10001;
vector<int> graph[SZ];
bool visited[SZ];
int n, m, cnt;
void dfs(int start)
{
cnt++;
visited[start] = true;
for (int i = 0; i < graph[start].size(); i++)
if (!visited[graph[start][i]])
dfs(graph[start][i]);
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(NULL);
cin >> n >> m;
vector<pii> v;
for (int i = 0; i < m; i++) {
int to, from;
cin >> to >> from;
graph[from].push_back(to);
}
for (int i = 1; i <= n; i++) {
dfs(i);
v.push_back({ ~cnt,i });
cnt = 0;
memset(visited, false, sizeof(visited));
}
sort(v.begin(), v.end());
cout << v[0].second << ' ';
for (int i = 1; i < v.size(); i++)
if (v[0].first == v[i].first)
cout << v[i].second << ' ';
return 0;
}
5. 소감
- 시간 초과 때문에 굉장히 애먹었었다.
- 한번 들린 곳을 안 들리게 만드는 게 관건인 문제였다.
- 시간 제한이 별도로 없어도, 이렇게 구현하는 습관을 들여야겠다.