1967번: 트리의 지름
파일의 첫 번째 줄은 노드의 개수 n(1 ≤ n ≤ 10,000)이다. 둘째 줄부터 n-1개의 줄에 각 간선에 대한 정보가 들어온다. 간선에 대한 정보는 세 개의 정수로 이루어져 있다. 첫 번째 정수는 간선이 연
www.acmicpc.net
풀이
1)
트리의 모든점에서 시작하여 리프노드에 갈때까지 가중치를 더해 큰 가중치를 구하는 방법을 사용했습니다.
일단, 통과는 했지만 실행속도가 다른 풀이에 비해 10배 가까이 느려 다른방법을 찾았습니다.
2)
우선 임의의 노드(저는 1번 노드를 사용했습니다)에서 시작해서 가장 긴 지름과 해당 지름을 갖는 도착 노드를 구하고 다시 한번 가장 긴 지름을 갖는 도착노드부터 시작하여 긴 지름을 찾게하였습니다.
자세한 사항은 코드의 주석을 참고해주세요.
코드
1)
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
public class Main {
public static class Edge {
int v, w;
public Edge(int v, int w) {
super();
this.v = v;
this.w = w;
}
}
public static int n, answer;
public static boolean[] visited;
public static List<Edge>[] edgeList;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = null;
n = Integer.parseInt(br.readLine());
// 노드는 1부터 시작하므로
visited = new boolean[n + 1];
edgeList = new ArrayList[n + 1];
for (int i = 0; i <= n; ++i) {
edgeList[i] = new ArrayList<Edge>();
}
for (int i = 0; i < n - 1; ++i) {
st = new StringTokenizer(br.readLine(), " ");
int from = Integer.parseInt(st.nextToken());
int to = Integer.parseInt(st.nextToken());
int weight = Integer.parseInt(st.nextToken());
// 방향이 없다는 의미는
// 양방향으로 갈 수 있다는 이야기
edgeList[from].add(new Edge(to, weight));
edgeList[to].add(new Edge(from, weight));
}
for (int i = 1; i <= n; ++i) {
// 현재점 방문처리
visited[i] = true;
// 지름 구하기
getRadius(i, 0);
// 다음 검사를 위해 방문처리 해제
visited[i] = false;
}
System.out.println(answer);
}
public static void getRadius(int v, int w) {
boolean isLeaf = true;
// 현재 점과 연결된 모든 점을 방문
for (Edge edge : edgeList[v]) {
// 만약 방문한 적이 있는 점이라면 방문 X
if (!visited[edge.v]) {
// 방문처리
visited[v] = true;
// 지름을 구하기 위해 현재까지 구한 지름에 방문하고자하는 다음 점까지의 길이를 더한다.
getRadius(edge.v, w + edge.w);
// 한 곳도 방문하지 못한경우 즉, 리프노드일 경우를 체크
isLeaf = false;
// 다음 검사를 위해 방문처리 해제
visited[v] = false;
}
}
// 만약 방문할 수 있는 정점이 없다면 즉, 리프노드라면
// 최장 길이가 될 수 있으므로 정답을 갱신
if (isLeaf) {
answer = (answer < w) ? w : answer;
return;
}
}
}
2)
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
public class Main {
public static class Edge {
int v, w;
public Edge(int v, int w) {
super();
this.v = v;
this.w = w;
}
}
public static int n, answer, maxIdx;
public static boolean[] visited;
public static List<Edge>[] edgeList;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = null;
n = Integer.parseInt(br.readLine());
// 노드는 1부터 시작하므로
edgeList = new ArrayList[n + 1];
for (int i = 0; i <= n; ++i) {
edgeList[i] = new ArrayList<Edge>();
}
for (int i = 0; i < n - 1; ++i) {
st = new StringTokenizer(br.readLine(), " ");
int from = Integer.parseInt(st.nextToken());
int to = Integer.parseInt(st.nextToken());
int weight = Integer.parseInt(st.nextToken());
// 방향이 없다는 의미는
// 양방향으로 갈 수 있다는 이야기
edgeList[from].add(new Edge(to, weight));
edgeList[to].add(new Edge(from, weight));
}
// 노드는 1부터 시작
visited = new boolean[n + 1];
// 지름 구하기
getRadius(1, 0);
// 가장 긴 지름을 갖고있는 노드와 연결된 간선은
// 가중치가 큰 수들로 이루어졌음이 보장되므로
// 해당 노드부터 시작하여 더 큰 지름을 구할 수 있다면
// 그 지름이 가장 긴 지름이 된다.
// 노드는 1부터 시작
visited = new boolean[n + 1];
getRadius(maxIdx, 0);
System.out.println(answer);
}
public static void getRadius(int v, int w) {
// 기존의 지름보다 큰 지름이라면
if (answer < w) {
// 지름 값 갱신
answer = w;
// 가장 긴 지름을 갖고있는 노드를 저장
maxIdx = v;
}
// 방문 처리
visited[v] = true;
// 현재 점과 연결된 모든 점을 방문
for (Edge edge : edgeList[v]) {
// 만약 방문한 적이 있는 점이라면 방문 X
if (!visited[edge.v]) {
// 지름을 구하기 위해 현재까지 구한 지름에 방문하고자하는 다음 점까지의 길이를 더한다.
getRadius(edge.v, w + edge.w);
}
}
}
}
GitHub - pyo7410/Algorithm: 1일 1커밋을 목표로!
1일 1커밋을 목표로! Contribute to pyo7410/Algorithm development by creating an account on GitHub.
github.com
'알고리즘 > 백준' 카테고리의 다른 글
[Java] BOJ 17298번 오큰수 (0) | 2021.08.12 |
---|---|
[Java] BOJ 1339번 단어 수학 (0) | 2021.08.11 |
[Java] BOJ 15685번 드래곤커브 (0) | 2021.08.06 |
[Java] BOJ 1504번 특정한 최단 경로 (0) | 2021.08.04 |
[Java] BOJ 1806번 부분합 (0) | 2021.08.03 |