Baekjoon/Gold

C++ / 백준 / 2637 / 장난감 조립

GitHubSeob 2023. 9. 9. 04:33
문제

 

https://www.acmicpc.net/problem/2637

 

2637번: 장난감 조립

첫째 줄에는 자연수 N(3 ≤ N ≤ 100)이 주어지는데, 1부터 N-1까지는 기본 부품이나 중간 부품의 번호를 나타내고, N은 완제품의 번호를 나타낸다. 그리고 그 다음 줄에는 자연수 M(3 ≤ M ≤ 100)이 주

www.acmicpc.net

 

문제풀이

 

다른 사람들의 풀이보다 벡터를 더 선언한 것 같다..

입력값들을 저장하는 input,

Y 부품을 만들기 위해 필요한 X의 개수를 저장하는 ingr 벡터, ingr[Y][X]=K;

기본 부품인지 나타내는 bool형 벡터 isBase,

들어오는 간선의 개수를 알려주는 indegree 벡터를 선언했다.

 

	for (int idx = 0; idx < M; ++idx) {
		cin >> X >> Y >> K;
		input[Y].push_back({ X,K });
		++indegree[X];
	}
	for (int idx = 1; idx < N; ++idx) {
		if (indegree[idx] == 0) {
			q.push(idx);
			isBase[idx] = true;
		}
	}

X를 만드는데 Y부품이 K개 필요하다는 입력이 들어온다.

위상정렬을 이용해 문제를 해결할 것이므로 input에는 재료인 Y에 완성품인 X와 K를 저장한다.

입력이 끝났으면 indegree값이 0인 부품을 찾는다.

이 부품들은 모두 기본 부품이라는 의미이다.

 

 

void topology_sort() {
	for (int i = 1; i <= N; ++i) {
		int num = q.front();
		q.pop();
		for (int idx = 0; idx < input[num].size(); ++idx) {
			int next = input[num][idx].first;
			int cnt = input[num][idx].second;
			if (isBase[num] == true) {
				ingr[next][num] += cnt;
			}
			else {
				for (auto iter = ingr[num].begin(); iter != ingr[num].end(); ++iter) {
					ingr[next][iter->first] += (iter->second * cnt);
				}
			}
			--indegree[next];
			if (indegree[next] == 0) q.push(next);
		}
	}
}

위상정렬 코드이다.

num은 입력에서 Y에 해당하고, next는 X에 해당하는 부품이다.

만약 num이 기본부품이면 ingr[next][num]에 cnt개수만큼 더한다.

기본 부품이 아니라면 ingr[num]에는 num을 만들기 위해 필요한 기본 부품들의 번호와 개수가 입력되어 있으므로 for문을 통해 모든 기본 부품들의 개수를 ingr[next]에 저장해 준다.

(예를 들어 5를 만드는데 1이 2개 필요하고, 7을 만드는데 5가 2개 필요하다고 가정하자,

부품1 * 2 -> 부품5, 부품5 * 2 -> 부품7 이런 식으로 표현할 수 있다.

부품 7을 만들기 위해서는 기본 부품 1이 총 4개가 필요하다)

 

그다음은 --indegree[next]을 하고 값이 0이 된다면 큐에 push 한다.

위 topology_sort 함수가 종료되면 반복문을 통해 ingr[완성품]의 기본 부품 개수들을 모두 출력하면 된다.

 

 

코드
#include <bits/stdc++.h>
#define pii pair<int, int>
using namespace std;

vector<map<int, int>>ingr;
vector<vector<pii>>input;
vector<bool>isBase;
vector<int>indegree;
queue<int>q;
int N;

void topology_sort() {
	for (int i = 1; i <= N; ++i) {
		int num = q.front();
		q.pop();
		for (int idx = 0; idx < input[num].size(); ++idx) {
			int next = input[num][idx].first;
			int cnt = input[num][idx].second;
			if (isBase[num] == true) {
				ingr[next][num] += cnt;
			}
			else {
				for (auto iter = ingr[num].begin(); iter != ingr[num].end(); ++iter) {
					ingr[next][iter->first] += (iter->second * cnt);
				}
			}
			--indegree[next];
			if (indegree[next] == 0) q.push(next);
		}
	}
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(NULL);

	int M(0);
	cin >> N >> M;
	isBase = vector<bool>(N + 1, false);
	ingr = vector<map<int, int>>(N + 1);
	input = vector<vector<pii>>(N + 1);
	indegree = vector<int>(N + 1, 0);

	int X(0), Y(0), K(0);

	for (int idx = 0; idx < M; ++idx) {
		cin >> X >> Y >> K;
		input[Y].push_back({ X,K });
		++indegree[X];
	}
	for (int idx = 1; idx < N; ++idx) {
		if (indegree[idx] == 0) {
			q.push(idx);
			isBase[idx] = true;
		}
	}

	topology_sort();

	for (auto iter = ingr[N].begin(); iter != ingr[N].end(); ++iter) {
		cout << iter->first << " " << iter->second << '\n';
	}
}