최소비용을 구해야하기 때문에 모든 경우에 대해서 탐색을 해야겠다는 생각을 해서 백트래킹을 생각함.

: dfs의 한계점
dfs로 한곳만 집중적으로 방문하는데, 아래의 반례 처리 못한다.
-> 부채꼴 형태의 그래프의 경우는 절대 풀 수 없다.

실행 결과

여행경로의 조건을 보면,

이러한 경우는 없다. 는 것을 증명할 수 있고, 여기서는 dfs 로 풀 수 있다.
-> a-> b, a->c
결론
: 한붓그리기의 취약점을 발견했다..





간선중에서 연결된 2개의 정점이 무엇이든 중요하지 않다.
아래의 0-1-2 순환 쪽을 보면, 비용이 5인 간선보다는 1과 2 비용의 간선을 선택하는 것이 0-1-2 번 노드를 연결하는데의 최소비용이다.
-> 여기서 유니온 파인드를 사용하자!
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
struct Edge
{
int startV;
int endV;
int cost;
// 2개의 연결된 정점에 무관하게
// 가장 낮은 cost 가중치대로 정렬하자.
bool operator<(Edge & e)
{
return cost < e.cost;
}
};
// 경로 압축해야 함.
int parentV[101];
int Find(int vvalue)
{
if(parentV[vvalue] == vvalue)
return vvalue;
return parentV[vvalue] = Find(parentV[vvalue]);
}
void Union(int a, int b)
{
int pA = Find(a);
int pB = Find(b);
if(pA < pB)
{
parentV[pB] = pA;
}
else if(pA > pB)
parentV[pA] = pB;
}
int solution(int n, vector<vector<int>> costs) {
int answer = 0;
// 1. 최소비용으로 모든 섬을 통행가능하게
// -> 순환구조를 만들 필요가 없다!
// 2. 어떤 간선을 선택하면서 최고의 간선을 선택할까?
// 3. 문제를 전부 읽어보면, 그래프는 일직선 형태가 아니라
// 그물형일 수 있다.
// 간선을 기준으로 해서 진행하자.
vector<Edge> edges;
for(auto iter : costs)
{
int sV = iter[0];
int eV = iter[1];
int cost = iter[2];
edges.push_back({sV, eV, cost});
}
sort(edges.begin(), edges.end());
// 크루스칼이므로, 유니온 파인드 개념을 가지고 와야 함.
for(int i = 0; i < 101; ++i)
{
parentV[i] = i;
}
// 오름차순으로 정렬된 edges를 가지고 진행하자.
for(auto iter : edges)
{
int sV = iter.startV;
int eV = iter.endV;
int cost = iter.cost;
if(Find(sV) != Find(eV))
{
Union(sV, eV);
answer += cost;
}
}
return answer;
}