티스토리 뷰
https://swexpertacademy.com/main/code/problem/problemDetail.do?contestProbId=AV15StKqAQkCFAYD
SW Expert Academy
SW 프로그래밍 역량 강화에 도움이 되는 다양한 학습 컨텐츠를 확인하세요!
swexpertacademy.com
문제 요약
주어진 섬들의 좌표로 가중치를 구하고, 가중치를 가지고 MST 구하기
입력
첫째줄의 테스트 케이스의 수 T가 주어진다.
이후 각 테스트 케이스의 첫 줄에는 섬의 개수 N이 주어지고 (1≤N≤1,000),
두 번째 줄에는 각 섬들의 정수인 X좌표, 세 번째 줄에는 각 섬들의 정수인 Y좌표가 주어진다 (0≤X≤1,000,000, 0≤Y≤1,000,000).
마지막으로, 해저터널 건설의 환경 부담 세율 실수 E가 주어진다 (0≤E≤1).
출력
각 테스트 케이스의 답을 순서대로 출력하며, 각 케이스마다 줄의 시작에 “#C”를 출력하여야 한다. 이때 C는 케이스의 번호이다.
같은 줄에 빈칸을 하나 두고, 주어진 입력에서 모든 섬들을 잇는 최소 환경 부담금을 소수 첫째 자리에서 반올림하여 정수 형태로 출력하라.
접근법
- N이 1000개이므로 O(N^2)로도 충분히 통과할 수 있다. N개의 점에 대해서 N-1개의 간선에 대한 가중치를 구하고, 해당 가중치를 벡터에 저장하고 정렬한다.
- 해당 가중치를 가지고 MST를 구하면 된다. 방법은 다양한데 나는 구현하기 쉬운 크루스칼 알고리즘을 썼다.
- 이후 구한 MST에 세율 E를 곱하고, 첫째 자리에서 반올림해서 정수 형태로 출력하면 되므로 구한 값에 round() 사용
시간 복잡도
가중치를 구하는데 O(N^2)만큼 소요되고, 구한 가중치를 정렬하는데 O(ElogE)만큼 소요된다. 이후 크루스칼 알고리즘은 N-1개의 간선을 구하면 종료되고, 최악의 경우 O(E)라고 생각했다. (마지막 간선을 선택하고 종료하는 경우)
이 문제는 20개를 합쳐 약 10초, 1개당 약 0.5초정도면 통과하므로 충분히 통과한다고 생각했다.
코드
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
|
#include <iostream>
#include <vector>
#include <algorithm>
#include <climits>
#include <math.h>
using namespace std;
#define ll long long
constexpr int VMAX = 1002, EMAX = 1000002;
constexpr long long int INF = LLONG_MAX;
typedef struct Edge
{
ll u, v, w;
Edge() : Edge(-1, -1, INF) {} // 생성자 1
Edge(ll uu, ll vv, ll ww) { u = uu, v = vv, w = ww; } // 생성자 2
bool operator <(Edge& O) { return w < O.w; }
}Edge;
ll v;
ll p[VMAX], r[VMAX], c[VMAX];
double cost;
Edge e[EMAX];
int find(int a)
{
if (p[a] < 0) return a;
return p[a] = find(p[a]);
}
bool merge(int a, int b)
{
a = find(a);
b = find(b);
if (a == b) return false;
p[b] = a;
return true;
}
void init()
{
cin >> v;
fill(r, r + VMAX, 0);
fill(c, c + VMAX, 0);
fill(p, p + VMAX, -1);
for (int i = 0; i < v; i++)
cin >> r[i];
for (int i = 0; i < v; i++)
cin >> c[i];
cin >> cost;
int cnt = 0;
for (int i = 0; i < v; i++)
{
for (int j = 0; j < v; j++)
{
if (i == j) continue;
e[cnt++] = Edge(i, j, ((abs(r[i] - r[j]) * abs(r[i] - r[j])) + ((abs(c[i] - c[j]) * abs(c[i] - c[j])))));
}
}
sort(e, e + EMAX);
}
ll solve()
{
ll res = 0;
int cnt = 0;
for (int i = 0; i < EMAX; i++)
{
if (merge(e[i].u, e[i].v))
{
res += e[i].w;
cnt++;
}
if (cnt == v - 1)
{
return round(res * cost);
}
}
}
int main()
{
cin.tie(0); ios::sync_with_stdio(0);
int t;
cin >> t;
for (int i = 1; i <= t; i++)
{
init();
cout << '#' << i << ' ' << solve() << "\n";
}
return 0;
}
|
cs |
몇 년 전에 자료구조 처음 공부할 때 MST랑 프림,크루스칼등을 배우고 유니온파인드를 배우고 넘어갔었는데, 그 당시에는 어렵다고 생각했는데 지금 다시 풀어보니까 생각보다 꽤 할만하다고 느꼈다.
+ 라이님의 블로그를 많이 참고했다.
https://blog.naver.com/kks227/220799105543
최소 스패닝 트리(Minimum Spanning Tree) (수정: 2019-01-29)
좀 쉬고 글을 이어서 씁니다. 최단 경로는 드디어 끝났고, 새로운 걸 배울 때가 됐습니다. 스패닝 트리(spa...
blog.naver.com
'PS > SWEA' 카테고리의 다른 글
(C++) [SWEA 1868번] 파핑파핑 지뢰찾기 (0) | 2023.02.07 |
---|---|
(C++) [SWEA 1248] [SW 문제해결 응용] - 3일차 공통조상 (0) | 2023.02.01 |
- Total
- Today
- Yesterday
- BOJ
- 상범 빌딩
- 6593
- 5397
- 2583
- 3190번
- 숨바꼭질 5
- 5427
- 3273
- 벽 부수고 이동하기 2
- 백준
- 3197
- 1475
- 파핑파핑 지뢰찾기
- 확장 게임
- 두 수의 합
- 16933
- 16920
- 1251
- 벽 부수고 이동하기 3
- 17071
- SWEA
- PS
- 6603
- 숨바꼭질 4
- 2146
- 구름톤챌린지
- 9328
- 2493
- DX부문
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 29 | 30 | 31 |