일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- bfs
- 백준 뒤집기 3
- 결정문제
- 깊이 우선 탐색
- 그래프탐색
- 그래프 이론
- 뒤집기 3
- 브루트포스
- 결정 문제
- 비트마스킹
- 재귀
- 1939백준
- 이분탐색
- Lis
- 최장증가수열
- disjoint set
- 구현
- 분할정복
- parametric search
- 최장길이바이토닉수열
- 그래프이론
- union find
- 백준 1464
- 이분 탐색
- DP
- boj 1464
- 그래프 탐색
- 패스트캠퍼스
- 서로소 집합
- 2493 백준
- Today
- Total
알고리즘 문제풀이
[BOJ] 1922번 - 네트워크 연결 본문
백준 1922번 - 네트워크 연결
시간제한 | 메모리 제한 | 제출 | 정답 | 맞은 사람 | 정답 비율 |
---|---|---|---|---|---|
2 초 | 256 MB | 17804 | 10333 | 6010 | 56.795% |
문제
도현이는 컴퓨터와 컴퓨터를 모두 연결하는 네트워크를 구축하려 한다. 하지만 아쉽게도 허브가 있지 않아 컴퓨터와 컴퓨터를 직접 연결하여야 한다. 그런데 모두가 자료를 공유하기 위해서는 모든 컴퓨터가 연결이 되어 있어야 한다. (a와 b가 연결이 되어 있다는 말은 a에서 b로의 경로가 존재한다는 것을 의미한다. a에서 b를 연결하는 선이 있고, b와 c를 연결하는 선이 있으면 a와 c는 연결이 되어 있다.)
그런데 이왕이면 컴퓨터를 연결하는 비용을 최소로 하여야 컴퓨터를 연결하는 비용 외에 다른 곳에 돈을 더 쓸 수 있을 것이다. 이제 각 컴퓨터를 연결하는데 필요한 비용이 주어졌을 때 모든 컴퓨터를 연결하는데 필요한 최소비용을 출력하라. 모든 컴퓨터를 연결할 수 없는 경우는 없다.
입력
첫째 줄에 컴퓨터의 수 N (1 ≤ N ≤ 1000)가 주어진다.
둘째 줄에는 연결할 수 있는 선의 수 M (1 ≤ M ≤ 100,000)가 주어진다.
셋째 줄부터 M+2번째 줄까지 총 M개의 줄에 각 컴퓨터를 연결하는데 드는 비용이 주어진다. 이 비용의 정보는 세 개의 정수로 주어지는데, 만약에 a b c 가 주어져 있다고 하면 a컴퓨터와 b컴퓨터를 연결하는데 비용이 c (1 ≤ c ≤ 10,000) 만큼 든다는 것을 의미한다. a와 b는 같을 수도 있다.
출력
모든 컴퓨터를 연결하는데 필요한 최소비용을 첫째 줄에 출력한다.
예제 입력 1
6
9
1 2 5
1 3 4
2 3 2
2 4 7
3 4 6
3 5 11
4 5 3
4 6 8
5 6 8
예제 출력 1
23
출처
www.acmicpc.net/problem/1922
알고리즘 분류
- 그래프 이론
- 최소 스패닝 트리
접근 방법
문제 조건을 해석해보면 완전 그래프가 주어졌을 때, Minimum Spanning Tree를 구하라는 의미 인 것을 알 수 있다.
Kruskal 알고리즘으로 접근해보자!
간단하게 kruskal 알고리즘은 다음과 같은 프로세스를 거친다.
1. 그래프에 존재하는 모든 간선(edge)들 중 선택하지 않는 간선들에 대해 가중치가 최소인 간선을 선택한다. ( 우선순위 큐로 구현하는 것이 효율적 )
2. 선택한 간선이 현재까지 방문한 좌표들과 Cycle을 이룰 경우 Minimum Spanning Tree의 간선으로 선택하지 않는다.
3. 만약, 선택한 간선이 현재까지 방문한 좌표들과 Cycle을 이루지 않을 경우 Minimum Spanning Tree의 간선으로 선택한다.
여기서 2,3번 프로세스는 서로소 집합으로 구현하는 것을 통해 상수 시간에 근접하는 시간복잡도로 사이클여부를 판단할 수 있다.
서로소 집합에 대해서는 포스팅 한 적이 있으므로 자세한 설명은 생략하겠다.
2020/12/12 - [자료구조 + 알고리즘/기초] - 서로소 집합 ( Disjoint Set Unit ) 자료구조
먼저, 방문하지 않은 정점들에 대한 간선들 중 cost가 최솟값인 edge를 선택하기 위해서, 그래프에 존재하는 모든 간선들을 Priority Queue에 넣어준다. 매 Stage마다, 남아있는 간선들 중 최솟값을 찾는 연산을 효율적이게 하기 위해서 MIN Heap tree 로 구현한 Priority Queue 에 모든 간선을 넣어두는 것이 좋다. ( 시간 복잡도는 log가 나옴 )
Minimum Spanning Tree 를 만들기 위해 필요한 간선은 N-1 ( N은 노드의 개수 ) 이므로, N-1번의 stage마다 위와 같은 process 를 수행한다.
먼저, 여러가지 구현 방법이 있겠지만 나는 Queue에 간선의 정보인 { 가중치, 시작 정점, 도착 정점 } 을 넣어서 시작 정점( 곧, 방문 했던 정점 ) 과 도착 정점간에 Cycle을 이룬다면 해당 간선은 추가하지 않고 폐기한다음, 다음 정점을 탐색해 나가는 방식으로 구현하였다.
N-1개의 간선이 추가되어야 하므로, 선택해야하는 간선의 수 cnt 를 N-1 로 설정한 다음 간선이 추가 되는 경우에만 1을 감소시키는 식으로 구현하였다.
소스 코드
#include <bits/stdc++.h>
using namespace std;
vector<pair<int,int>> adj[1001];
int parent[1001], rnk[1001];
int find(int u){
if( u == parent[u] )
return u;
return parent[u] = find(parent[u]);
}
bool _union(int u, int v){
u = find(u), v = find(v);
if( u == v )
return false;
if( rnk[u] > rnk[v] )
swap(u,v);
parent[u] = v;
if( rnk[u] == rnk[v] )
rnk[v] += 1;
return true;
}
int main(void){
ios_base::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
int N,M;
cin >> N >> M;
// init
for(int i=1; i<=N; i++){
rnk[i] = 1;
parent[i] = i;
}
// 모든 컴퓨터를 연결하는데 필요한 최소비용 필요
for(int i=0; i<M; i++){
int a,b,c;
cin >> a >> b >> c;
adj[a].push_back({c, b});
}
// 코스트, 전, 후
priority_queue<tuple<int,int,int>, vector<tuple<int,int,int>>, greater<tuple<int,int,int>>> PQ;
for(int i=1; i<=N; i++){
for( auto info : adj[i] ){
PQ.push({info.first, i, info.second});
}
}
int cnt = N-1;
long long min_cost = 0;
while(cnt){
tuple<int,int,int> top = PQ.top();
PQ.pop();
if( find(get<1>(top)) == find(get<2>(top)) )
continue;
_union(get<1>(top), get<2>(top));
min_cost += get<0>(top);
cnt -= 1;
}
cout << min_cost;
return 0;
}
'자료구조 + 알고리즘 > [BOJ]' 카테고리의 다른 글
[BOJ] 1005번 - ACM Craft (0) | 2020.12.30 |
---|---|
[BOJ] 2056번 - 작업 (0) | 2020.12.30 |
[BOJ] 1439번 - 뒤집기 (0) | 2020.12.28 |
[BOJ] 9466번 - 텀 프로젝트 (0) | 2020.12.27 |
[BOJ] 1806 번 - 부분합 (0) | 2020.12.27 |