코딩테스트/백준

[백준][C++]1197번 최소 스패닝 트리

윤깡패 2023. 7. 13. 17:20

문제

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

 

1197번: 최소 스패닝 트리

첫째 줄에 정점의 개수 V(1 ≤ V ≤ 10,000)와 간선의 개수 E(1 ≤ E ≤ 100,000)가 주어진다. 다음 E개의 줄에는 각 간선에 대한 정보를 나타내는 세 정수 A, B, C가 주어진다. 이는 A번 정점과 B번 정점이

www.acmicpc.net

 

 

풀이

최소 신장 트리(Minimum Spanning Tree) 자료구조

 

최소 신장 트리(Minimum Spanning Tree) 자료구조

최소 신장 트리(Mininum Spanning Tree) 자료구조 그래프에서 모든 노드를 연결할 때 사용된 에지들의 가중치의 합을 최소로 하는 신장 트리 * 신장 트리(Spanning Tree) : 하나의 그래프가 있을 때 모든 노

soobin0821.tistory.com

 

 

코드

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

int find_parent(int n);
void union_parent(int a, int b);
static vector<int> parent;

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

  int V, E;
  cin >> V >> E;

  vector<tuple<int, int, int>> graph;
  
  for(int i = 0; i < E; i++)
  {
    int A, B, C;
    cin >> A >> B >> C;

    graph.push_back(make_tuple(C, A, B));
  }

  sort(graph.begin(), graph.end());	// 오름차순 정렬
  reverse(graph.begin(), graph.end());

  parent.resize(V + 1);
  for(int i = 0; i <= V; i++)
  {
    parent[i] = i;  // 자기 자신의 index값으로 초기화
  }

  int count = 1;
  long result = 0;
  while(count < V)
  {
    int cost = get<0>(graph.back());
    int node1 = get<1>(graph.back());
    int node2 = get<2>(graph.back());
    graph.pop_back();

    if(find_parent(node1) != find_parent(node2))  // 같은 부모가 아니라면 ⇒ 연결해도 사이클이 생기지 않는다면
    {
      count++;  // 사용 에지 수 1 증가
      result += cost;  // 에지의 가중치를 정답 변수에 더하기
      union_parent(node1, node2);  // union_parent 연산 수행
    }
  }

  cout << result;  // 정답 변수 출력

  return 0;
}

// find_parent 연산
int find_parent(int n)
{
  if(parent[n] == n)
  {
    return n;
  }
  else
  {
    return parent[n] = find_parent(parent[n]);  // 재귀 함수 형태로 구현 ⇒ 경로 압축 부분
  }
}

// union_parent 연산 : 대표 노드끼리 연결
void union_parent(int a, int b)
{
  // a와 b의 대표 노드 찾기
  a = find_parent(a);
  b = find_parent(b);

  if(a < b)
  {
    parent[b] = a;
  }
  else if(b < a)
  {
    parent[a] = b;
  }
}

 

 

오답

더보기
#include <iostream>
#include <queue>
using namespace std;

void munion(int a, int b);
int find(int a);
static vector<int> parent;

// 에지 정보 구조체 생성, 가중치 값 기준 오름차순 정렬로 설정
typedef struct Edge
{
  int s, e, v;
  bool operator > (const Edge& temp) const
  {
    return v > temp.v;
  }
} Edge;

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

  int N, M;
  cin >> N >> M;
  priority_queue<Edge, vector<Edge>, greater<Edge>> pq;  // 오름차순 정렬
  parent.resize(N + 1);

  for(int i = 0; i <= N; i++)
  {
    parent[i] = i;
  }
  for(int i = 0; i < M; i++)
  {
    int s, e, v;
    cin >> s >> e >> v;
    pq.push(Edge{s, e, v});
  }

  int useEdge = 0;
  int result = 0;

  while(useEdge < N - 1)
  {
    Edge now = pq.top();
    pq.pop();
    // 같은 부모가 아니라면 -> 연결해도 사이클이 생기지 않는다면
    if(find(now.s) != find(now.e))
    {
      munion(now.s, now.e);
      result = result + now.v;
      useEdge++;
    }
  }
  cout << result;
}

// union 연산 : 대표 노드끼리 연결
void munion(int a, int b)
{
  a = find(a);
  b = find(b);

  if(a != b)
  {
    parent[b] = a;
  }
}

// find 연산
int find(int a)
{
  if(a == parent[a])
  {
    return a;
  }
  else
  {
    // 재귀 함수 형태로 구현 -> 경로 압축 부분
    return parent[a] = find(parent[a]);
  }
}

 

 

 

 

 

728x90