본문 바로가기

알고리즘/백준 문제풀이

[백준 1325번] 효율적인 해킹 / C++ (메모리 초과)

문제

해커 김지민은 잘 알려진 어느 회사를 해킹하려고 한다. 이 회사는 N개의 컴퓨터로 이루어져 있다. 김지민은 귀찮기 때문에, 한 번의 해킹으로 여러 개의 컴퓨터를 해킹 할 수 있는 컴퓨터를 해킹하려고 한다.

이 회사의 컴퓨터는 신뢰하는 관계와, 신뢰하지 않는 관계로 이루어져 있는데, A가 B를 신뢰하는 경우에는 B를 해킹하면, A도 해킹할 수 있다는 소리다.

이 회사의 컴퓨터의 신뢰하는 관계가 주어졌을 때, 한 번에 가장 많은 컴퓨터를 해킹할 수 있는 컴퓨터의 번호를 출력하는 프로그램을 작성하시오.

입력

첫째 줄에, N과 M이 들어온다. N은 10,000보다 작거나 같은 자연수, M은 100,000보다 작거나 같은 자연수이다. 둘째 줄부터 M개의 줄에 신뢰하는 관계가 A B와 같은 형식으로 들어오며, "A가 B를 신뢰한다"를 의미한다. 컴퓨터는 1번부터 N번까지 번호가 하나씩 매겨져 있다.

출력

첫째 줄에, 김지민이 한 번에 가장 많은 컴퓨터를 해킹할 수 있는 컴퓨터의 번호를 오름차순으로 출력한다.

풀이

문제 자체는 어렵지 않았다. dfs를 이용하면 금방 해결되는 문제였지만 자꾸 메모리 초과가 나서 꽤 애를 먹었었다.

처음에는 dfs함수 안에서 재귀호출을 하도록 코드를 작성했었는데 그 부분때문에 메모리 초과가 나는거였다.

그래서 메인함수에서 반복문을 이용해 dfs함수를 호출하는 방법으로 수정하였다.

#include<vector>
#include<iostream>
#include<algorithm>
#include<stack>
#include<map>
#define _CRT_SECURE_NO_WARNINGS
using namespace std;
int n, m;
vector<int> res;
vector<vector<int>> arr;

int dfs(int start) {
	vector<int> visited(arr.size());
	stack<int> need_visit;
	int cnt = 0;
	int node = start;

	need_visit.push(node);

	while (!need_visit.empty()) {
		int node = need_visit.top();
		need_visit.pop();
		if (visited[node] == 0) {
			visited[node] = 1;
			cnt++;
			for (int i = 0; i < arr[node].size(); i++) {
				need_visit.push(arr[node][i]);
			}
		}
	}

	res[start] = cnt;

	return cnt;
}

int main() {

	int max = 0;
	cin >> n >> m;
	arr.resize(n + 1);
	res.resize(n + 1);
	for (int i = 0; i < m; i++) {
		int x, y;
		cin >> x >> y;
		arr[y].push_back(x);
	}

	for (int i = 1; i < n + 1; i++) {
		int cnt = dfs(i);
		if(max < cnt)
			max = cnt;
	}

	for (int i = 1; i < n + 1; i++) {
		if (res[i] == max)
			cout << i << " ";
	}
}