백준
[C++] 백준 칵테일
MINU.SHINNNN
2023. 3. 20. 15:34
https://www.acmicpc.net/problem/1033
1033번: 칵테일
august14는 세상에서 가장 맛있는 칵테일이다. 이 칵테일을 만드는 정확한 방법은 아직 세상에 공개되지 않았지만, 들어가는 재료 N개는 공개되어 있다. 경근이는 인터넷 검색을 통해서 재료 쌍 N
www.acmicpc.net
풀이
칵테일에 들어가는 N-1개 재료의 비가 주어질 때, 각 재료의 질량 총합이 최소가 되도록 하는 각각의 재료 질량을 구하는 문제입니다.
따라서, 최대 공약수와 최소 공배수를 활용해서 문제를 해결할 수 있고, N개 중 N-1개의 값이 주어지므로 사이클 없는 그래프입니다.
a, b, p, q 형태로 값이 주어질 때,
- a재료와 b 재료의 최대 공약수(gcd(p, q))로 나눈 재료비(ex. 9:6 -> 3:2)를 구합니다.
- 각 재료의 현재 질량에 재료비를 곱해주면, 원하는 질량비를 만들기 위해 곱해줘야하는 수를 구할 수 있습니다. ex) a질량 4 b질량 3, 재료비 3:2를 맞춰야 할 때, 4x:3y = 3:2 가 성립하므로, 9y = 8x 입니다.
- 우리는 모든 질량 총합이 최소가 되어야 하므로, 재료비를 곱해준 재료 질량의 최대 공약수를 구하여 나눠준 값으로 업데이트 한다.
- 업데이트 시, 연결된 모든 노드를 같이 업데이트 한다.
#include <iostream>
#include <vector>
#include <cstring>
using namespace std;
struct mat {
int val = 1;
vector<int> edge;
}arr[11];
bool visited[11];
int gcd(int a, int b)
{
int tmp = 0;
if (a < b) {
tmp = a;
a = b;
b = tmp;
}
if (a % b == 0) return b;
else
return gcd(b, a%b);
}
void update(int node, int mod)
{
arr[node].val *= mod; // 비율 반영
visited[node] = true;
for (auto e : arr[node].edge) {
if (!visited[e]) {
update(e, mod);
}
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
// freopen("test.txt", "r", stdin);
int n, a, b, p, q, gcdVal, amod, bmod;
cin >> n;
for (int i=0; i < n-1; i++) {
cin >> a >> b >> p >> q;
gcdVal = gcd(p, q);
amod = arr[b].val * p / gcdVal;
bmod = arr[a].val * q / gcdVal;
gcdVal = gcd(amod, bmod);
memset(visited, 0, sizeof visited);
update(a, amod/gcdVal);
update(b, bmod/gcdVal);
arr[a].edge.push_back(b);
arr[b].edge.push_back(a);
}
for (int i=0; i<n; i++)
cout << arr[i].val << " ";
return 0;
}