티스토리 뷰
[programmers] 258711번 - 도넛과 막대 그래프(BFS, 2024 KAKAO WINTER INTERNSHIP)
AGAPE1225 2024. 5. 18. 15:191. 문제 및 예제
카카오 문제에 신나게 달려들었다가 멘탈 박살났다. 처음 들어갈때는 "이게 왜 LV.2야 ㄷㄷ" 라는 생각이 들었는데, 풀다보니 "이게 왜 LV.2야?" 라는 생각이 계속 들었다. ㅋㅋ 임의로 생성된 노드를 구하는 방법이 진입 간선과 진출 간선의 수를 가지고 구한다는 생각을 하지 못해 결국 남의 풀이를 찾아 보았다. 역시 카카오는 기발한 생각으로 쉽게 문제를 풀 수 있거나 문자열과 같이 미친 집중력과 피지컬을 요구하는 쌩짜 구현 이 둘로 나뉘는 것 같다. 불평 해봤자 달라질 건 없으니 해당 방법으로 임의의 노드를 구하고 각 그래프의 종류를 구했다. 각 그래프의 종류를 구하는 방법은 어렵지 않았다. (솔직히 간선의 수로 다 해결할 수 있는 문제였구나를 나중에 깨달았다.)
https://school.programmers.co.kr/learn/courses/30/lessons/258711?language=cpp
2. 풀이과정
문제는 다음처럼 나눴다.
1. 임의로 배치된 노드를 구한다.
- 해당 노드를 구하면 이 노드와 연결된 점 부터 탐색을 시작하면 되기에 문제가 수월해 질 것이라고 생각했다.
2. 그래프의 종류를 구한다.
다음은 임의의 노드를 구하는 과정이다.
#include <string>
#include <vector>
#include <queue>
using namespace std;
vector<int> graph[1000001];
int count_in[1000001] = {0};
int count_out[1000001] = {0};
int get_ans_node(){
int max_node = 0;
int max_node_size = -1;
for(int i = 0; i < 1000001; i++){
//node is in graph
if(count_in[i] == 0 && count_out[i] >= 2){
return i;
}
}
return -1;
}
vector<int> solution(vector<vector<int>> edges) {
vector<int> answer = {0, 0, 0, 0};
int ans_node = -1;
//정점을 구한다.
//create graph
for(int i = 0; i < edges.size(); i++){
graph[edges[i][0]].push_back(edges[i][1]);
count_in[edges[i][1]]++;
count_out[edges[i][0]]++;
}
int start_node = get_ans_node();
answer[0] = start_node;
return answer;
}
그냥 진입 간선과 진출 간선을 카운트해주기만 했다. 들어오는 간선인 "진입 간선"의 수가 0이어야한다. 임의로 생성된 노드는 각 그래프를 연결하는 노드이기 때문이다. 그러나 이렇게만으로 판별하면 안된다. 막대 모양 그래프의 시작 노드도 진입 간선의 수가 0이기 때문이다. 따라서 이 노드와의 예외를 두기 위해 진출 간선이 2개 이상이라는 조건도 추가해서 구했다.
다음은 그래프 타입을 구하는 과정이다. 탐색알고리즘은 BFS를 사용했다. 전체 정답 코드를 적어보았다.
#include <string>
#include <vector>
#include <queue>
using namespace std;
vector<int> graph[1000001];
int count_in[1000001] = {0};
int count_out[1000001] = {0};
int get_ans_node(){
int max_node = 0;
int max_node_size = -1;
for(int i = 0; i < 1000001; i++){
//node is in graph
if(count_in[i] == 0 && count_out[i] >= 2){
return i;
}
}
return -1;
}
int get_graph_type(int start_node){
queue<int> q;
if(graph[start_node].size() != 1){
if(graph[start_node].size() == 0)
return 2;
else
return 3;
}
q.push(graph[start_node][0]);
while(true){
int node = q.front();
q.pop();
if(graph[node].size() != 1){
if(graph[node].size() == 0)
return 2;
else
return 3;
}
if(node == start_node)
return 1;
q.push(graph[node][0]);
}
}
vector<int> solution(vector<vector<int>> edges) {
vector<int> answer = {0, 0, 0, 0};
int ans_node = -1;
//정점을 구한다.
//create graph
for(int i = 0; i < edges.size(); i++){
graph[edges[i][0]].push_back(edges[i][1]);
count_in[edges[i][1]]++;
count_out[edges[i][0]]++;
}
int start_node = get_ans_node();
answer[0] = start_node;
for(int i = 0; i < graph[start_node].size(); i++){
int root_node = graph[start_node][i];
int graph_type = get_graph_type(root_node);
answer[graph_type]++;
}
return answer;
}
각 타입 그래프의 특징을 정하면 다음과 같다.
1. 도넛형: 탐색하다가 시작 노드를 만나면 도넛형
2. 막대형: 탐색하다가 진출 간선이 0인 노드를 만다면 막대형
3. 8자형: 탐색하다가 시작 노드를 만나기 전, 진출 간선의 수가 2개인 노드를 만나면 8자형
해당 조건만 판별하면 됐다.
3. 결어
결국 블로그를 찾아보았지만 손에 익숙해지는 연습의 필요성을 느끼게 되었다. 화이팅!
'programming > 알고리즘 풀이' 카테고리의 다른 글
[programmers] 258712번 - 가장 많이 받은 선물(DP, 2024 KAKAO WINTER INTERNSHIP) (4) | 2024.09.21 |
---|---|
[백준 알고리즘] 2579번 - 계단오르기 (Dynamic programming) (1) | 2024.06.30 |
[programmers] 1835번 - 단체사진 찍기(Brute force, 2017 카카오코드 본선) (1) | 2023.11.16 |
[programmers] 92342번 - 양궁대회 (BFS, 2022 KAKAO BLIND RECRUITMENT) (1) | 2023.11.15 |
[programmers] 150368번 - 이모티콘 할인행사 (brute force, 2023 KAKAO BLIND RECRUITMENT) (2) | 2023.10.24 |
- Total
- Today
- Yesterday
- 자료구조
- java
- 안드로이드 프로그래밍
- 개발자
- BaekJoon
- 코딩
- Programmers
- CJ
- spring
- 문자열
- 후기
- 코테
- Spring Boot
- C언어
- 육군
- 코딩테스트
- 백준 알고리즘
- 프로그래머스
- Python
- c++
- 백준
- 안드로이드 스튜디오
- 백준알고리즘
- 구현
- CJ 올리브네트웍스
- 알고리즘
- XML
- 비트코인
- CJ Olivenetworks
- 기록지
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |