https://school.programmers.co.kr/learn/courses/30/lessons/42861

 

프로그래머스

SW개발자를 위한 평가, 교육의 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프

programmers.co.kr

 

4번째 코드 정답

#include <string>
#include <vector>
#include<algorithm>
#include<iostream>
using namespace std;


//크루스칼알고리즘
//1. 비용 기준 높은 순 정렬, 2. 유니온파인드, 3. n-1개 간선 까지의 비용 합
int org[101]; // 섬 100이하  , bool 타입으로 하면 segmentation 에러 발생 유의
bool comp(vector<int> base, vector<int> tar) {
	return base[2] < tar[2]; // std::sort 비교함수는 strict weak ordering 규칙을 따라야 해서 같을 때 반드시 false를 반환해야한다. 즉 <= 으로 true 시 런타임에러 발생 가능
}

int getParent(int now)
{
	if (org[now] == now) return now; // 0번째 섬부터 시작하는데 0이 보스가 아닐 수 있으나 항상 여기서 리턴됨.

	int ret = getParent(org[now]);
	org[now] = ret; // 최상위 부모노드의 자식들을 일렬로 배치
	return ret;
}
bool unionFind(int src1, int src2) {
	int parent1 = getParent(src1);
	int parent2 = getParent(src2);
	if (parent1 == parent2) return false;
	org[parent1] = parent2;
	return true;
}
int solution(int n, vector<vector<int>> costs) {
	int answer = 0; // 간선 비용 합
	int cnt = 0; // n-1개 카운팅 용도

	//초기 부모를 자기자신으로 초기화
	for (int idx = 0; idx < sizeof(org) / sizeof(org[0]); ++idx) org[idx] = idx;
	sort(costs.begin(), costs.end(), comp);

	for (int idx = 0; idx < costs.size(); ++idx) { 
		bool isConn = unionFind(costs[idx][0], costs[idx][1]);
		if (isConn) {
			cnt++;
			answer += costs[idx][2];
			if (cnt == n - 1)break;
		}
	}
	return answer;
}

 

유니온파인드에서는 어떤 순서로 인자 값을 넣든 결과는 같다. org[parent1] = parent2 로 합치기 때문에 인자 순서가 바뀌어도 동일 그룹이 된다. 

 

 

세번째 코드 오답

if (org[now] == 0) return now; // 0번째 섬부터 시작하는데 0이 보스가 아닐 수 있으나 항상 여기서 리턴됨.

 

 

두번째 코드 (크루스칼 알고리즘을 이용한 MST 기법 활용)

-그래프에서 최소 비용으로 모든 구간을 거쳐가는 문제이기에 MST(Minimum Spanning Tree)를 사용해야한다.

#include <string>
#include <vector>
#include<algorithm>
#include<iostream>
using namespace std;


//크루스칼알고리즘
//1. 비용 기준 높은 순 정렬, 2. 유니온파인드, 3. n-1개 간선 까지의 비용 합
int org[101]; // 섬 100이하  , bool 타입으로 하면 segmentation 에러 발생 유의
bool comp(vector<int> base, vector<int> tar) {
	return base[2] < tar[2]; // std::sort 비교함수는 strict weak ordering 규칙을 따라야 해서 같을 때 반드시 false를 반환해야한다. 즉 <= 으로 true 시 런타임에러 발생 가능
}

int getParent(int now)
{
	if (org[now] == 0) return now; // 0번째 섬부터 시작하는데 0이 보스가 아닐 수 있으나 항상 여기서 리턴됨.
	
    int ret = getParent(org[now]);
	org[now] = ret; // 최상위 부모노드의 자식들을 일렬로 배치
	return ret;
}
bool unionFind(int src1, int src2) {
	int parent1 = getParent(src1);
	int parent2 = getParent(src2);
	if (parent1 == parent2) return false;
	org[parent1] = parent2;
	return true;
}
int solution(int n, vector<vector<int>> costs) {
	int answer = 0; // 간선 비용 합
	int cnt = 0; // n-1개 카운팅 용도
	sort(costs.begin(), costs.end(), comp);
	for (int idx = 0; idx < costs.size(); ++idx) { // costs.size()까지가 아닌 n-1 간선(n 정점 갯수 - 1)까지
		//0번째 인덱스와 1번째 인덱스 중 작은 값이 보스로 통일

		bool isConn = unionFind(costs[idx][0], costs[idx][1]);
		if (isConn) {
			cnt++;
			answer += costs[idx][2];
			if (cnt == n - 1)break;
		}
	}
	return answer;
}

 

두번째 코드 오답

논리는 모두 맞으나 마지막 for 조건문에서 n-1이 아니다. isConn 필터링으로 인해 n-1개 까지 실제 크루스칼알고리즘이 적용되지 않을 수 있기 때문이다. 이때는 isConn 조건문에 true 횟수가 n-1개 까지 진행하기위한 counting을 해야한다.

#include <string>
#include <vector>
#include<algorithm>
#include<iostream>
using namespace std;


//크루스칼알고리즘
//1. 비용 기준 높은 순 정렬, 2. 유니온파인드, 3. n-1개 간선 까지의 비용 합
int org[101]; // 섬 100이하  , bool 타입으로 하면 segmentation 에러 발생 유의
bool comp(vector<int> base, vector<int> tar) {
    return base[2] < tar[2]; // std::sort 비교함수는 strict weak ordering 규칙을 따라야 해서 같을 때 반드시 false를 반환해야한다. 즉 <= 으로 true 시 런타임에러 발생 가능
}

int getParent(int now)
{
    if (org[now] == 0) return now;
    int ret = getParent(org[now]);
    org[now] = ret; // 최상위 부모노드의 자식들을 일렬로 배치
    return ret;
}
bool unionFind(int src1, int src2) {
    int parent1 = getParent(src1);
    int parent2 = getParent(src2);
    if (parent1 == parent2) return false;
    org[parent1] = parent2;
    return true;
}
int solution(int n, vector<vector<int>> costs) {
    int answer = 0;
    sort(costs.begin(), costs.end(), comp);
    for (int idx = 0; idx < n - 1; ++idx) { // costs.size()까지가 아닌 n-1 간선(n 정점 갯수 - 1)까지
        bool isConn = unionFind(costs[idx][0], costs[idx][1]);
        if (isConn) {
            answer += costs[idx][2];
        }
    }
    return answer;
}

 

 

첫번째 코드 오답

 

오답 이유: 간선이 중요하지 정점이 중요한게 아니다. visited로 간선여부가 고려되지 않는다. 

#include <string>
#include <vector>
#include<algorithm>
#include<iostream>
using namespace std;
/*
1. 비용 낮음->높음 순 정렬
2. visited 체크
*/
bool visited[101];
bool comp(vector<int> b, vector<int> tar){
    return b[2] <= tar[2];
}
int solution(int n, vector<vector<int>> costs) {
    int answer = 0;
    sort(costs.begin(), costs.end(), comp);
    for(int idx = 0; idx < costs.size(); ++idx){
        int src = costs[idx][0];
        int dst = costs[idx][1];
        if(visited[src] == 0 || visited[dst] == 0){
            cout<<src<< " "<< dst<<endl;
            visited[src] = 1;
            visited[dst] = 1;
            answer+=costs[idx][2];
        }
    }
    return answer;
}

 

 

 

개념 참고해보기

https://chanhuiseok.github.io/posts/algo-33/

 

알고리즘 - 크루스칼 알고리즘(Kruskal Algorithm), 최소 신장 트리(MST)

##

chanhuiseok.github.io

 

최소신장트리를 구하기 위한 크루스칼알고리즘은 그리디의 일종

 

최소신장트리 중 Prim 알고리즘 관련 영상 및 블로그

https://www.youtube.com/watch?v=y_25iKuQO5o

 

 

https://ansohxxn.github.io/algorithm/mst/

 

(C++) 최소 신장 트리 MST, 크루스칼 알고리즘, 프림 알고리즘

🌜 신장 트리 Spanning Tree

ansohxxn.github.io

 

'프로그래머스 > 코딩테스트' 카테고리의 다른 글

lv2) 멀리 뛰기  (0) 2026.06.16
비트마스킹 관련 연습 (7다)  (0) 2026.06.03
lv3 ) 기지국 설치 [다시]  (0) 2026.05.28
lv3 ) 야근 지수  (0) 2026.05.27
lv2) 올바른괄호 []  (0) 2026.05.27

+ Recent posts