본문 바로가기

Algorithm

백준 15591번 MooTube (Silver)

반응형

문제

농부 존은 남는 시간에 MooTube라 불리는 동영상 공유 서비스를 만들었다. MooTube에서 농부 존의 소들은 재밌는 동영상들을 서로 공유할 수 있다. 소들은 MooTube에 1부터 N까지 번호가 붙여진 N (1 ≤ N ≤ 5,000)개의 동영상을 이미 올려 놓았다. 하지만, 존은 아직 어떻게 하면 소들이 그들이 좋아할 만한 새 동영상을 찾을 수 있을지 괜찮은 방법을 떠올리지 못했다.

농부 존은 모든 MooTube 동영상에 대해 “연관 동영상” 리스트를 만들기로 했다. 이렇게 하면 소들은 지금 보고 있는 동영상과 연관성이 높은 동영상을 추천 받을 수 있을 것이다.

존은 두 동영상이 서로 얼마나 가까운 지를 측정하는 단위인 “USADO”를 만들었다. 존은 N-1개의 동영상 쌍을 골라서 직접 두 쌍의 USADO를 계산했다. 그 다음에 존은 이 동영상들을 네트워크 구조로 바꿔서, 각 동영상을 정점으로 나타내기로 했다. 또 존은 동영상들의 연결 구조를 서로 연결되어 있는 N-1개의 동영상 쌍으로 나타내었다. 좀 더 쉽게 말해서, 존은 N-1개의 동영상 쌍을 골라서 어떤 동영상에서 다른 동영상으로 가는 경로가 반드시 하나 존재하도록 했다. 존은 임의의 두 쌍 사이의 동영상의 USADO를 그 경로의 모든 연결들의 USADO 중 최솟값으로 하기로 했다.

존은 어떤 주어진 MooTube 동영상에 대해, 값 K를 정해서 그 동영상과 USADO가 K 이상인 모든 동영상이 추천되도록 할 것이다. 하지만 존은 너무 많은 동영상이 추천되면 소들이 일하는 것이 방해될까 봐 걱정하고 있다! 그래서 그는 K를 적절한 값으로 결정하려고 한다. 농부 존은 어떤 K 값에 대한 추천 동영상의 개수를 묻는 질문 여러 개에 당신이 대답해주기를 바란다.

입력

입력의 첫 번째 줄에는 N과 Q가 주어진다. (1 ≤ Q ≤ 5,000)

다음 N-1개의 줄에는 농부 존이 직접 잰 두 동영상 쌍의 USADO가 한 줄에 하나씩 주어진다. 각 줄은 세 정수 pi, qi, ri (1 ≤ pi, qi ≤ N, 1 ≤ ri ≤ 1,000,000,000)를 포함하는데, 이는 동영상 pi와 qi가 USADO ri로 서로 연결되어 있음을 뜻한다.

다음 Q개의 줄에는 농부 존의 Q개의 질문이 주어진다. 각 줄은 두 정수 ki와 vi(1 ≤ ki ≤ 1,000,000,000, 1 ≤ vi ≤ N)을 포함하는데, 이는 존의 i번째 질문이 만약 K = ki라면 동영상 vi를 보고 있는 소들에게 몇 개의 동영상이 추천될 지 묻는 것이라는 것을 뜻한다.

출력

Q개의 줄을 출력한다. i번째 줄에는 농부 존의 i번째 질문에 대한 답변이 출력되어야 한다.

 

 

실수 

1. 전체 경로의 최소 값을 다 구하고 시도하면 시간 초과 

=> 만약 a -> c로 가는데 도중 경로가 a -> b , b -> c 라면 a -> b 가 k보다 작을 때 이미 a -> c는 k이상의 값을 가질 수 없게 된다.

따라서 이를 이용해서 모든 간선의 최소거리 미리 찾을 필요 없이 탐색에서 k 이상이면 큐에 넣고 카운트 올리는 식으로 돌리면 됨.

 

2. 2차원 배열을 사용했는데 경로가 많지 않아 탐색자체에 시간이 많이 소요된다.

따라서 벡터를 통해서 확장 배열형태로 구현해야 시간 초과가 안남...

#include<iostream>
#include<string.h>
#include<vector>
#include<queue>
using namespace std;

int N, Q;
vector<pair<int, int> > vec[5001];



int main(int argc, char** argv)
{
	cin >> N >> Q;

	for (int i = 0; i < N - 1; i++)
	{
		int a, b, c;
		cin >> a >> b >> c;
		vec[a].push_back({ b,c });
		vec[b].push_back({ a,c });
	}


	for (int i = 0; i < Q; i++)
	{
		int k, s;
		cin >> k >> s;


		bool visit[5001];
		memset(visit, 0, sizeof(visit));

		visit[s] = true;
		queue<int> que;
		que.push(s);

		int count = 0;
		while (!que.empty())
		{
			int cur = que.front();
			que.pop();

			for (int j = 0; j < vec[cur].size(); j++)
			{
				if (!visit[vec[cur][j].first])
				{
					if (vec[cur][j].second >= k)
					{
						count++;
						visit[vec[cur][j].first] = true;
						que.push({ vec[cur][j].first });
					}
				}
			}
		}
		cout << count << endl;
	}




	return 0;//정상종료시 반드시 0을 리턴해야합니다.
}
반응형

'Algorithm' 카테고리의 다른 글

백준 2529번 부등호  (0) 2020.09.07
백준 10021번 Watering the Fields  (0) 2020.09.07
백준 1520번 내리막길  (0) 2020.09.06
sw 3143. 가장 빠른 문자열 타이핑  (0) 2020.09.06
백준 14225번 부분수열의 합  (0) 2020.09.05