반응형
16947번: 서울 지하철 2호선
첫째 줄에 역의 개수 N(3 ≤ N ≤ 3,000)이 주어진다. 둘째 줄부터 N개의 줄에는 역과 역을 연결하는 구간의 정보가 주어진다. 같은 구간이 여러 번 주어지는 경우는 없고, 역은 1번부터 N번까지 번호
www.acmicpc.net

풀이 ) DFS
- 각 역이 순환선에 포함된 역인지 확인
- 사이클에서 지선이 있는 역에서부터 각 지선 노선의 거리 구하기
위의 순서대로 DFS만을 이용해서 구했다.
먼저 각 역이 순환선인지 확인하기 위해 모든 점에 대해서 현재 점으로 되돌아 오는지 확인했다. (checkCycle()) 이때 순환선을 확인하면 순환선 내의 역은 한번에 구해 반복 횟수를 줄일 수 있다. (return type이 boolean인 이유)
순환역에 속한 역 중 차수가 3 이상인 역은 지선으로 갈 수 있는 역이므로 이 역을 시작으로해서 지선에 포함된 역까지의 거리를 구한다. (getDistance())
코드 )
import java.io.*;
import java.util.*;
class Main {
static int n;
static List<Integer>[] adj;
static boolean[] visited;
static boolean[] isCycle;
static int[] distance;
public static void main(String[] args) throws IOException {
input();
checkCycle(); // 사이클 확인
getDistance(); // 거리 구하기
}
static void getDistance() {
distance = new int[n+1];
visited = new boolean[n+1];
// 사이클에서 벗어나는 길 거리 구하기
for(int i = 1; i <= n; ++i)
if(isCycle[i] && adj[i].size() > 2)
searchRoute(i);
// 거리 출력
StringBuilder sb = new StringBuilder();
for(int i = 1; i <= n; ++i) {
sb.append(distance[i] + " ");
}
System.out.println(sb.toString());
}
static void searchRoute(int i) {
for(int next: adj[i]) {
if(isCycle[next] || distance[next] > 0) {
continue;
}
distance[next] = distance[i]+1;
searchRoute(next);
}
}
static void checkCycle() {
isCycle = new boolean[n+1];
for(int i = 1; i <= n; ++i)
if(!isCycle[i]) {
visited = new boolean[n+1];
dfs(i, i, 0);
}
}
static boolean dfs(int strt, int i, int cnt) {
for(int next: adj[i]) {
if(next == strt) {
// 바로 돌아오는 경우를 cnt를 사용해서 방지
if (cnt > 1)
return isCycle[i] = true;
else
continue;
}
// 다음이 사이클(사이클이 아닌 곳에서 사이클로 -> 사이클 아님)
// 현재가 사이클(조건 만족)
// 이미 방문(사이클인지 여부가 이미 나옴)
if(isCycle[next] || isCycle[i] || visited[next])
continue;
visited[next] = true;
isCycle[i] = dfs(strt, next, cnt+1);
}
return isCycle[i];
}
static void input() throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
n = Integer.parseInt(br.readLine());
adj = new List[n+1];
for(int i = 1; i <= n; ++i)
adj[i] = new ArrayList<>();
for(int i = 0; i < n; ++i) {
StringTokenizer st = new StringTokenizer(br.readLine(), " ");
// 양방향
int v1 = Integer.parseInt(st.nextToken());
int v2 = Integer.parseInt(st.nextToken());
adj[v1].add(v2);
adj[v2].add(v1);
}
}
}
알게된 점 )
그래프에서 정점과 간선의 개수가 같고 모두 이어져 있으면 사이클은 단 하나만 가능하다.
반응형
'문제풀이 > 백준' 카테고리의 다른 글
[JAVA] 백준 - 1774 : 우주신과의 교감 (0) | 2021.09.09 |
---|---|
[JAVA] 백준 - 16236 : 아기상어 (0) | 2021.09.04 |
[JAVA] 백준 - 17612 : 쇼핑몰 (0) | 2021.04.02 |
[JAVA] 백준 - 2263 : 트리의 순회 (0) | 2021.02.28 |
[JAVA] 백준 - 10819 : 차이를 최대로 (0) | 2021.02.27 |