거의 알고리즘 일기장

백준 9172 _ 상근이의 여행 본문

알고리즘 문제풀이

백준 9172 _ 상근이의 여행

건우권 2020. 4. 4. 22:17

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

 

9372번: 상근이의 여행

문제 상근이는 겨울방학을 맞아 N개국을 여행하면서 자아를 찾기로 마음먹었다.  하지만 상근이는 새로운 비행기를 무서워하기 때문에, 최대한 적은 종류의 비행기를 타고 국가들을 이동하려고 한다. 이번 방학 동안의 비행 스케줄이 주어졌을 때, 상근이가 가장 적은 종류의 비행기를 타고 모든 도시들을 여행할 수 있도록 도와주자. 상근이가 한 국가에서 다른 국가로 이동할 때 다른 국가를 거쳐 가도(심지어 이미 방문한 국가라도) 된다. 입력 첫 번째 줄에는 테스트 케

www.acmicpc.net

 

1. 풀이방법

 

문제를 보자마자 정점-1을 출력하면 되지않나? 라는 의문이 들었고 정답처리가 되긴했다.

하지만, 정점 -1 출력은 너무 허무해서 나는 한번 아까 한번본 유니온 파인드의 개념을 이용해서 풀어보기도 했다.

 

union -find -> 최상위 부모노드를 저장하는 배열을 만들고 정점을 이을때마다 배열의 값을 갱신한다.

 


 

2. 코드 ( 첫번째 풀이 (정점 -1)만 출력하면 답임, 두번째 풀이만 올리겠음 )

 

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

vector<pair<int, int>> edge;
int parents[1002];
int N;
void parentsInit(int n)
{
	for (int i = 1; i <= n; i++)
		parents[i] = i;
}

int getParent(int n)
{
	if (parents[n] == n) return n;
	return parents[n] = getParent(parents[n]);
}

void update(int ori, int change)
{
	for (int i = 1; i <= N; i++)
		if (parents[i] == ori)
			parents[i] = change;
}

void makeUnion(int a, int b)
{
	int x = getParent(a);
	int y = getParent(b);
	if (x < y)
		update(y, x);
	else
		update(x, y);
}

int main()
{
	int t;
	cin >> t;

	int n, m;
	for (int i = 0; i < t; i++)
	{
		cin >> n >> m;
		N = n;

		parentsInit(n);
		int result = 0;

		//간선 입력
		int a, b;
		for (int j = 0; j < m; j++)
		{
			cin >> a >> b;
			edge.push_back({ a, b });
		}

		//간선을 전체 순회하며 계산
		for (int j = 0; j < (int)edge.size(); j++)
		{
			int firstPlace = edge[j].first;
			int secondPlace = edge[j].second;
			if (parents[firstPlace] != parents[secondPlace])
			{
				makeUnion(firstPlace, secondPlace);
				result++;
			}
		}

		cout << result << '\n';
		edge.clear();
	}

	return 0;
}

 

 


 

3. 후기

 

유니온 파인드의 개념과 설명을 유명한 블로그에서 보고 이용해서 짜봤는데 처음짜는거라 그런지 솔직히 더럽게 못짰다. 또 뭔가 유니온 파인드를 잘못짠거 같기도 한데 ..

 


아.. 틀린거 같아서 다시 공부해보니 위에것은 유니온 파인드 알고리즘도 뭣도 아닙니다. 잘못짰네요. 

반응형
Comments