Skip to content

Commit 1bc4fd6

Browse files
committed
[level 2] Title: 도넛과 막대 그래프, Time: 3162.51 ms, Memory: 844 MB -BaekjoonHub
1 parent b5e19ea commit 1bc4fd6

File tree

2 files changed

+199
-0
lines changed

2 files changed

+199
-0
lines changed
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
# [level 2] 도넛과 막대 그래프 - 258711
2+
3+
[문제 링크](https://school.programmers.co.kr/learn/courses/30/lessons/258711#qna)
4+
5+
### 성능 요약
6+
7+
메모리: 844 MB, 시간: 3162.51 ms
8+
9+
### 구분
10+
11+
코딩테스트 연습 > 2024 KAKAO WINTER INTERNSHIP
12+
13+
### 채점결과
14+
15+
정확성: 100.0<br/>합계: 100.0 / 100.0
16+
17+
### 제출 일자
18+
19+
2026년 03월 03일 23:02:59
20+
21+
### 문제 설명
22+
23+
<p>도넛 모양 그래프, 막대 모양 그래프, 8자 모양 그래프들이 있습니다. 이 그래프들은 1개 이상의 정점과, 정점들을 연결하는 단방향 간선으로 이루어져 있습니다.</p>
24+
25+
<ul>
26+
<li>크기가 <code>n</code>인 도넛 모양 그래프는 <code>n</code>개의 정점과 <code>n</code>개의 간선이 있습니다. 도넛 모양 그래프의 아무 한 정점에서 출발해 이용한 적 없는 간선을 계속 따라가면 나머지 <code>n</code>-1개의 정점들을 한 번씩 방문한 뒤 원래 출발했던 정점으로 돌아오게 됩니다. 도넛 모양 그래프의 형태는 다음과 같습니다.</li>
27+
</ul>
28+
29+
<p><img src="https://grepp-programmers.s3.ap-northeast-2.amazonaws.com/files/production/dbf6ff18-1f05-46c2-8b62-7c39e831d1c6/%E1%84%8C%E1%85%A6%E1%84%86%E1%85%A9%E1%86%A8%20%E1%84%8B%E1%85%A5%E1%86%B9%E1%84%82%E1%85%B3%E1%86%AB%20%E1%84%83%E1%85%A1%E1%84%8B%E1%85%B5%E1%84%8B%E1%85%A5%E1%84%80%E1%85%B3%E1%84%85%E1%85%A2%E1%86%B7.drawio.png" title="" alt="제목 없는 다이어그램.drawio.png"></p>
30+
31+
<ul>
32+
<li>크기가 <code>n</code>인 막대 모양 그래프는 <code>n</code>개의 정점과 <code>n</code>-1개의 간선이 있습니다. 막대 모양 그래프는 임의의 한 정점에서 출발해 간선을 계속 따라가면 나머지 <code>n</code>-1개의 정점을 한 번씩 방문하게 되는 정점이 단 하나 존재합니다. 막대 모양 그래프의 형태는 다음과 같습니다.</li>
33+
</ul>
34+
35+
<p><img src="https://grepp-programmers.s3.ap-northeast-2.amazonaws.com/files/production/85e3e66c-bba0-4da3-9552-c467dfe5baf4/%E1%84%83%E1%85%A9%E1%84%82%E1%85%A5%E1%86%BA%E1%84%80%E1%85%AA%E1%84%86%E1%85%A1%E1%86%A8%E1%84%83%E1%85%A22.png" title="" alt="도넛과막대2.png"></p>
36+
37+
<ul>
38+
<li>크기가 <code>n</code>인 8자 모양 그래프는 <code>2n</code>+1개의 정점과 <code>2n</code>+2개의 간선이 있습니다. 8자 모양 그래프는 크기가 동일한 2개의 도넛 모양 그래프에서 정점을 하나씩 골라 결합시킨 형태의 그래프입니다. 8자 모양 그래프의 형태는 다음과 같습니다.</li>
39+
</ul>
40+
41+
<p><img src="https://grepp-programmers.s3.ap-northeast-2.amazonaws.com/files/production/868f2c14-8521-4c94-a2f0-1e11708aa76a/8%E1%84%8C%E1%85%A1%E1%84%80%E1%85%B3%E1%84%85%E1%85%A2%E1%84%91%E1%85%B3.drawio.png" title="" alt="8자그래프.drawio.png"></p>
42+
43+
<p>도넛 모양 그래프, 막대 모양 그래프, 8자 모양 그래프가 여러 개 있습니다. 이 그래프들과 무관한 정점을 하나 생성한 뒤, 각 도넛 모양 그래프, 막대 모양 그래프, 8자 모양 그래프의 임의의 정점 하나로 향하는 간선들을 연결했습니다.<br>
44+
그 후 각 정점에 서로 다른 번호를 매겼습니다.<br>
45+
이때 당신은 그래프의 간선 정보가 주어지면 생성한 정점의 번호와 정점을 생성하기 전 도넛 모양 그래프의 수, 막대 모양 그래프의 수, 8자 모양 그래프의 수를 구해야 합니다.</p>
46+
47+
<p>그래프의 간선 정보를 담은 2차원 정수 배열 <code>edges</code>가 매개변수로 주어집니다. 이때, 생성한 정점의 번호, 도넛 모양 그래프의 수, 막대 모양 그래프의 수, 8자 모양 그래프의 수를 순서대로 1차원 정수 배열에 담아 return 하도록 solution 함수를 완성해 주세요.</p>
48+
49+
<hr>
50+
51+
<h5>제한사항</h5>
52+
53+
<ul>
54+
<li>1 ≤ <code>edges</code>의 길이 ≤ 1,000,000
55+
56+
<ul>
57+
<li><code>edges</code>의 원소는 [<code>a</code>,<code>b</code>] 형태이며, <code>a</code>번 정점에서 <code>b</code>번 정점으로 향하는 간선이 있다는 것을 나타냅니다.</li>
58+
<li>1 ≤ <code>a</code>, <code>b</code> ≤ 1,000,000</li>
59+
</ul></li>
60+
<li>문제의 조건에 맞는 그래프가 주어집니다. </li>
61+
<li>도넛 모양 그래프, 막대 모양 그래프, 8자 모양 그래프의 수의 합은 2이상입니다.</li>
62+
</ul>
63+
64+
<hr>
65+
66+
<h5>입출력 예</h5>
67+
<table class="table">
68+
<thead><tr>
69+
<th>edges</th>
70+
<th>result</th>
71+
</tr>
72+
</thead>
73+
<tbody><tr>
74+
<td>[[2, 3], [4, 3], [1, 1], [2, 1]]</td>
75+
<td>[2, 1, 1, 0]</td>
76+
</tr>
77+
<tr>
78+
<td>[[4, 11], [1, 12], [8, 3], [12, 7], [4, 2], [7, 11], [4, 8], [9, 6], [10, 11], [6, 10], [3, 5], [11, 1], [5, 3], [11, 9], [3, 8]]</td>
79+
<td>[4, 0, 1, 2]</td>
80+
</tr>
81+
</tbody>
82+
</table>
83+
<hr>
84+
85+
<h5>입출력 예 설명</h5>
86+
87+
<p><strong>입출력 예 #1</strong></p>
88+
89+
<p>주어진 그래프를 그림으로 나타내면 다음과 같습니다.</p>
90+
91+
<p><img src="https://grepp-programmers.s3.ap-northeast-2.amazonaws.com/files/production/1511016b-7d9b-427d-a57f-653a9abcd7fe/%E1%84%83%E1%85%A9%E1%84%82%E1%85%A5%E1%86%BA%E1%84%80%E1%85%AA%E1%84%86%E1%85%A1%E1%86%A8%E1%84%83%E1%85%A23.png" title="" alt="도넛과막대3.png"></p>
92+
93+
<p>2번 정점이 생성한 정점이고 도넛 모양 그래프 1개, 막대 모양 그래프 1개가 존재합니다. 따라서 [2, 1, 1, 0]을 return 해야 합니다.</p>
94+
95+
<p><strong>입출력 예 #2</strong></p>
96+
97+
<p>주어진 그래프를 그림으로 나타내면 다음과 같습니다.</p>
98+
99+
<p><img src="https://grepp-programmers.s3.ap-northeast-2.amazonaws.com/files/production/0c6a6010-3bfe-4578-b3f3-1c75381673b9/%E1%84%83%E1%85%A9%E1%84%82%E1%85%A5%E1%86%BA%E1%84%80%E1%85%AA%E1%84%86%E1%85%A1%E1%86%A8%E1%84%83%E1%85%A24.drawio.png" title="" alt="도넛과막대4.drawio.png"></p>
100+
101+
<p>4번 정점이 생성한 정점이고 막대 모양 그래프 1개, 8자 모양 그래프 2개가 존재합니다. 따라서 [4, 0, 1, 2]를 return 해야 합니다.</p>
102+
103+
<hr>
104+
105+
<p>※ 공지 - 2024년 1월 23일 테스트 케이스가 추가되었습니다. 기존에 제출한 코드가 통과하지 못할 수도 있습니다.</p>
106+
107+
108+
> 출처: 프로그래머스 코딩 테스트 연습, https://school.programmers.co.kr/learn/challenges
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
import java.util.*;
2+
3+
class Solution {
4+
5+
int root, n;
6+
ArrayList<Integer>[] graph;
7+
int[][] inOut = new int[1000000][2];
8+
public int[] solution(int[][] edges) {
9+
int[] answer = new int[4];
10+
n = findEdgeInfo(edges);
11+
root = findRoot();
12+
graph = makeGraph(edges);
13+
14+
for(int i = 0; i < graph[root].size(); i++){
15+
answer[search(graph[root].get(i))]++;
16+
}
17+
18+
answer[0] = root;
19+
return answer;
20+
}
21+
22+
int search(Integer node){
23+
inOut[node][1]--;
24+
if(inOut[node][0] == 0 && inOut[node][1] == 0) return 2;
25+
Queue<Integer> q = new ArrayDeque<>();
26+
boolean[] visited = new boolean[n + 1];
27+
visited[node] = true;
28+
q.add(node);
29+
30+
int next, now;
31+
while(!q.isEmpty()){
32+
now = q.poll();
33+
34+
// 막대 그래프: 나가는 간선 ( inOut[now][0] ) : 0, 들어가는 간선 ( inOut[now][1] ) : 1
35+
if(inOut[now][0] == 0 && inOut[now][1] == 1) return 2;
36+
// 8자 그래프 : 나가는 간선 ( inOut[now][0] ) : 2, 들어가는 간선 ( inOut[now][1] ) : 2
37+
if(inOut[now][0] == 2 && inOut[now][1] == 2) return 3;
38+
39+
for(int i = 0; i < graph[now].size(); i++){
40+
next = graph[now].get(i);
41+
if(now == next) return 1;
42+
if(root == next || visited[next]) continue;
43+
44+
visited[next] = true;
45+
q.add(next);
46+
47+
}
48+
}
49+
return 1;
50+
}
51+
52+
int findRoot(){
53+
for(int i = 1; i < n + 1; i++) {
54+
if(inOut[i][0] - inOut[i][1] > 1) {
55+
return i;
56+
}
57+
}
58+
return 0;
59+
}
60+
61+
int findEdgeInfo(int[][] edges){
62+
int s, e, n = 0;
63+
for(int i = 0; i < edges.length; i++){
64+
s = edges[i][0];
65+
e = edges[i][1];
66+
67+
inOut[s][0]++;
68+
inOut[e][1]++;
69+
n = Math.max(n, Math.max(s, e));
70+
}
71+
72+
return n;
73+
}
74+
75+
ArrayList[] makeGraph(int[][] edges){
76+
ArrayList[] makingGraph = new ArrayList[n + 1];
77+
for(int i = 0; i < n + 1; i++) {
78+
makingGraph[i] = new ArrayList<Integer>();
79+
}
80+
81+
int s, e;
82+
for(int i = 0; i < edges.length; i++){
83+
s = edges[i][0];
84+
e = edges[i][1];
85+
86+
makingGraph[s].add(e);
87+
}
88+
89+
return makingGraph;
90+
}
91+
}

0 commit comments

Comments
 (0)