문제 링크
https://www.acmicpc.net/problem/1033
접근 방법
비례식 여러 개를 합치는 문제입니다.
예를 들어 1) A : B = 2 : 3이고 2) A : C = 8 : 6이면 A : B : C = 4 : 6 : 3이 됩니다.
1)의 A와 C 값을 곱하면 12가 되고, 1) 에는 C가 없으므로 8이 됩니다.
곱한 결과값의 최대공약수는 4이므로 4로 나눠주면 3과 2가 됩니다.
1) 에다가 2를 곱해주고, 1)에 C가 없으므로 3을 넣어주면 4 : 6 : 3이 됩니다.
소스 코드
import java.util.*;
import java.io.*;
public class Main {
static ArrayList<ArrayList<Integer>> arr;
static int[] answer;
static int n, visit;
static int gcd(int a, int b) {
return b == 0 ? a : gcd(b, a % b);
}
static void cocktail(int num, int mul) { // dfs
answer[num] *= mul;
visit |= (1 << num);
for (int i : arr.get(num)) {
if ((visit & (1 << i)) == 0) {
visit |= (1 << i);
cocktail(i, mul);
}
}
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int a, b, p, q, tmp1, tmp2, div;
n = Integer.parseInt(br.readLine());
answer = new int[n];
arr = new ArrayList<>(n);
for (int i = 0; i < n; i++) {
answer[i] = 1;
arr.add(new ArrayList<>());
}
for (int i = 0; i < n - 1; i++) {
StringTokenizer st = new StringTokenizer(br.readLine());
a = Integer.parseInt(st.nextToken());
b = Integer.parseInt(st.nextToken());
p = Integer.parseInt(st.nextToken());
q = Integer.parseInt(st.nextToken());
tmp1 = answer[b] * p;
tmp2 = answer[a] * q;
div = gcd(tmp1, tmp2);
visit = 0;
cocktail(a, tmp1 / div);
cocktail(b, tmp2 / div);
arr.get(a).add(b);
arr.get(b).add(a);
}
for (int i = 0; i < n; i++) {
System.out.print(answer[i] + " ");
}
}
}
코드 설명
입력받은 비율에서 얼마를 곱해야 전에 구한 비례식들과 합칠 수 있는지 계산합니다.
cocktail 메서드를 이용하여 연결된 노드의 비율 값을 재귀적으로 갱신합니다.
그 후에 각 인접리스트에 추가해 줍니다.
'코딩테스트 > 백준' 카테고리의 다른 글
[백준 JAVA] 1753. 최단경로 (0) | 2024.08.01 |
---|---|
[백준 JAVA] 16472. 고냥이 (0) | 2024.07.25 |
[백준 JAVA] 2824. 최대공약수 (0) | 2024.07.11 |
[백준 JAVA] 14232. 보석 도둑 (0) | 2024.07.09 |
[백준 JAVA] 1456. 거의 소수 (0) | 2024.07.03 |