728x90
효율적인 해킹
시간 제한메모리 제한제출정답맞힌 사람정답 비율
5 초 | 256 MB | 56945 | 10792 | 7122 | 19.694% |
문제
해커 김지민은 잘 알려진 어느 회사를 해킹하려고 한다. 이 회사는 N개의 컴퓨터로 이루어져 있다. 김지민은 귀찮기 때문에, 한 번의 해킹으로 여러 개의 컴퓨터를 해킹 할 수 있는 컴퓨터를 해킹하려고 한다.
이 회사의 컴퓨터는 신뢰하는 관계와, 신뢰하지 않는 관계로 이루어져 있는데, A가 B를 신뢰하는 경우에는 B를 해킹하면, A도 해킹할 수 있다는 소리다.
이 회사의 컴퓨터의 신뢰하는 관계가 주어졌을 때, 한 번에 가장 많은 컴퓨터를 해킹할 수 있는 컴퓨터의 번호를 출력하는 프로그램을 작성하시오.
입력
첫째 줄에, N과 M이 들어온다. N은 10,000보다 작거나 같은 자연수, M은 100,000보다 작거나 같은 자연수이다. 둘째 줄부터 M개의 줄에 신뢰하는 관계가 A B와 같은 형식으로 들어오며, "A가 B를 신뢰한다"를 의미한다. 컴퓨터는 1번부터 N번까지 번호가 하나씩 매겨져 있다.
출력
첫째 줄에, 김지민이 한 번에 가장 많은 컴퓨터를 해킹할 수 있는 컴퓨터의 번호를 오름차순으로 출력한다.
예제 입력 1 복사
5 4
3 1
3 2
4 3
5 3
예제 출력 1 복사
1 2
https://www.acmicpc.net/problem/1325
흐름
코드
#include <bits/stdc++.h>
using namespace std;
int n,m,a,b,cnt, ret, r[10004];
vector<int> adj[10004], answer;
void dfs(int here){
cnt++;
for(int there: adj[here]){
dfs(there);
cout <<there << "\n";
}
return;
}
int main(){
ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
//1. 입력받기
cin >> n >> m;
for(int i=0;i<m;i++){
cin >> a >> b;
adj[b].push_back(a); //부모-자식
}
//2. 노드마다 dfs 수행
for(int i=0;i<n;i++){
cnt = 0;
dfs(i);
r[i]=cnt;
ret = max(cnt,ret);
}
//3. cnt 가장 큰 노드 저장하기
for(int i=0;i<n;i++){
if(r[i]==ret) answer.push_back(i);
}
//4. 오름차순 정렬하여 출력하기
sort(answer.begin(), answer.end());
for(int a:answer) cout << a << " ";
return 0;
}
시간초과가 떴다?!
질문 게시판을 보니 다들 dfs,bfs로 풀 때 어떤 포인트를 해결하지 못하면 시간초과가 났다. => 방문 배열!
틀린 이유
- 트리 구조로만 한정되는 것이 아니라, 그래프 구조도 가능하다. => 방문한 곳을 또 방문하면 시간초과
- dfs 시에는 가능하면 visited 배열을 사용하자.
- n개의 컴퓨터이고, 각 컴퓨터는 자연수 번호를 가지고 있다. => 나는 0부터 n-1 노드만 탐색하여 전범위 커버가 안됐다.
- 문제 숫자 조건 확인하기!
- 틀린 이유는 아니지만 오름차순으로 정렬하여 출력할 필요가 없다. 1번 노드부터 차례대로 수를 저장하기 때문에 노드 번호를 출력하면 오름차순으로 출력된다.
고친 코드
#include <bits/stdc++.h>
using namespace std;
int n,m,a,b,cnt, ret, r[10004], visited[10004];
vector<int> adj[10004];
void dfs(int here){
visited[here]=1;
cnt++; //노드 수 추가
for(int there: adj[here]){
if(!visited[there]) dfs(there);
}
return;
}
int main(){
ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
//1. 입력받기
cin >> n >> m;
for(int i=0;i<m;i++){ //신뢰관계
cin >> a >> b;
adj[b].push_back(a); //부모-자식
}
//2. 노드마다 dfs 수행
for(int i=1;i<=n;i++){ //자연수 N개의 노드 탐색
cnt = 0;
fill(visited, visited+10004, 0); //초기화
dfs(i);
r[i]=cnt; //노드 수 저장
ret = max(cnt,ret); //최대값 구하기
}
//3. 정답 출력
for(int i=1;i<=n;i++) if(r[i]==ret) cout << i << " ";
return 0;
}
맞았다!
선생님 코드는 dfs 함수가 void 가 아닌 int를 반환하는 함수였다. 변수 사용하는 패턴이 더 깔끔하기때문에 다음에는 int형 반환 함수 방식도 생각하자!
int형 반환 dfs
#include <bits/stdc++.h>
using namespace std;
int n,m,a,b,cnt, answer, r[10004], visited[10004];
vector<int> adj[10004];
int dfs(int here){
int ret = 1;
visited[here]=1;
for(int there: adj[here]){
if(!visited[there]) {
ret += dfs(there);
}
}
return ret;
}
int main(){
ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
//1. 입력받기
cin >> n >> m;
for(int i=0;i<m;i++){ //신뢰관계
cin >> a >> b;
adj[b].push_back(a); //부모-자식
}
//2. 노드마다 dfs 수행
for(int i=1;i<=n;i++){ //자연수 N개의 노드 탐색
fill(visited, visited+10004, 0);
r[i] = dfs(i);
answer = max(r[i],answer); //최대값 구하기
}
//3. 정답 출력
for(int i=1;i<=n;i++) {
if(r[i]==answer)
cout << i << " ";
}
return 0;
}
728x90
'알고리즘 > 알고리즘 문제풀이' 카테고리의 다른 글
3주차: 완전 탐색, 백트래킹, 1189번(컴백홈), 17825번(주사위윷놀이), 17136번(색종이붙이기) (0) | 2023.02.12 |
---|---|
17298번: 오큰수 [C++] (0) | 2023.02.08 |
2636번: 치즈 [C++] (0) | 2023.02.07 |
14502번: 연구소 [C++] (0) | 2023.02.07 |
9012번: 괄호 [C++] (0) | 2023.02.05 |