1922번: 네트워크 연결
이 경우에 1-3, 2-3, 3-4, 4-5, 4-6을 연결하면 주어진 output이 나오게 된다.
www.acmicpc.net
최소 스패닝 트리를 구하는 문제였다. 크루스칼 알고리즘을 사용하면 간단히 풀 수 있다.
#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
class OptimizedDisjoinSet {
vector<int> parent, rank;
public:
OptimizedDisjoinSet(int n) : parent(n), rank(n, 1)
{
for (int i = 0; i < n; i++)
parent[i] = i;
}
int find(int u)
{
if (u == parent[u]) return u; //자기 자신을 가리키면 뿌리노드임
return parent[u] = find(parent[u]); // 위에 부모노드가 있다면 재귀호출
}
void merge(int u, int v)
{
u = find(u); v = find(v);
if (u == v) return; // 뿌리노드가 서로 같다면 걸러낸다
// rank[u]의 높이가 더 높다면 rank[u]랑 rank[v]를 바꾼다
if (rank[u] > rank[v]) swap(u, v);
// 이제 무조건 rank[u]의 높이가 더 낮으므로 u를 v의 자식으로 넣는다
parent[u] = v;
// rank[u]와 rank[v]의 높이가 같다면 rank[v] 높이를 1 증가시킨다.
if (rank[u] == rank[v]) ++rank[v];
}
};
const int MAX_V = 1001;
int V, E;
vector<pair<int, int>> adj[MAX_V];
int kruskal()
{
vector<pair<int, pair<int, int>>> edges;
for (int u = 1; u < V + 1; u++)
for (int i = 0; i < adj[u].size(); i++)
{
int v = adj[u][i].first;
int cost = adj[u][i].second;
edges.push_back({ cost, {u, v} });
}
sort(edges.begin(), edges.end());
OptimizedDisjoinSet sets(V+1);
int ret = 0;
for (int i = 0; i < edges.size(); i++)
{
int cost = edges[i].first;
int u = edges[i].second.first, v = edges[i].second.second;
if (sets.find(u) == sets.find(v)) continue;
sets.merge(u, v);
ret += cost;
}
return ret;
}
int main(void) {
cin >> V >> E;
for (int i = 0; i < E; i++) {
int a, b, c;
cin >> a >> b >> c;
adj[a].push_back({ b,c });
}
cout << kruskal() << endl;
return 0;
}

알고리즘 200일 프로젝트 - 164 day
'알고리즘 > BOJ' 카테고리의 다른 글
백준 1707번: 이분 그래프 (0) | 2020.09.20 |
---|---|
백준 1916번: 최소비용 구하기 (0) | 2020.09.20 |
백준 1197번: 최소 스패닝 트리 (0) | 2020.09.19 |
백준 2252번: 줄 세우기 (0) | 2020.09.19 |
백준 13460번: 구슬 탈출 2 (0) | 2020.09.19 |