반응형
https://www.acmicpc.net/problem/3176
3176번: 도로 네트워크
첫째 줄에 N이 주어진다. (2 ≤ N ≤ 100,000) 다음 N-1개 줄에는 도로를 나타내는 세 정수 A, B, C가 주어진다. A와 B사이에 길이가 C인 도로가 있다는 뜻이다. 도로의 길이는 1,000,000보다 작거나 같은 양
www.acmicpc.net
[ 문제풀이 ]
이 문제를 풀기 전에 다음 글을 읽고 오시는 것을 추천드립니다!
https://rudalsd.tistory.com/95?category=1073064
[ 자료구조 ] 희소 배열(Sparse Table)
1. 희소 배열(Sparse Table) - 배열 원소의 개수가 무조건 배열의 length 값보다 작은 배열 - 희소 배열은 배열의 원소 위치가 연속적이지 않은 배열 2. 희소 배열 만들기 보통 5번 노드에서 1번 노드까
rudalsd.tistory.com
1. 희소 배열의 각 노드에 max, min 값을 각각 저장해줍니다.
2. 두 노드의 높이를 맞춰줄 때 Max, Min을 계속 갱신해줍니다.
3. Min과 Max를 출력해줍니다.
[ 소스 코드 ]
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 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 | #include<cstdio> #include<vector> #include<cmath> using namespace std; struct node { int to; int max; int min; }; int N, K; int H; //트리의 높이 node arr[100001][18]; vector<vector<node>> list; int visited[100001]; int h[100001]; //노드의 높이 void dfs(int cur) //arr[cur][0] 채우기 { if (visited[cur] == 1) return; visited[cur] = 1; for (auto next : list[cur]) { if (visited[next.to] != 1) { arr[next.to][0] = { cur, next.max, next.min }; h[next.to] = h[cur] + 1; dfs(next.to); } } } void makeTree() //트리 만들기 { for (int i = 1; i <= H; i++) { for (int j = 1; j <= N; j++) { auto next = arr[j][i - 1]; if (arr[next.to][i-1].to != 0) { int Max = max(next.max, arr[next.to][i - 1].max); int Min = min(next.min, arr[next.to][i - 1].min); arr[j][i] = { arr[next.to][i - 1].to, Max, Min }; } } } } void Dist(int a, int b) //a, b 사이의 가장 긴 도로와 짧은 도로 길이 구하기 { if (h[a] > h[b]) { //a가 트리의 더 위에 있도록 int temp = a; a = b; b = temp; } int Min = 987654321; int Max = 0; if (h[a] != h[b]) { //높이가 다르다면 맞춰주기 for (int i = H; i >= 0; i--) { int mask = 1 << i; if (h[b] - h[a] >= mask) { Min = min(Min, arr[b][i].min); Max = max(Max, arr[b][i].max); b = arr[b][i].to; } if (h[a] == h[b]) break; } } if(a!=b) { //같은 높이일 때 서로 다른 숫자면 for (int i = H; i >= 0; i--) { if (arr[a][i].to == arr[b][i].to || arr[a][i].to == 0 || arr[b][i].to == 0) continue; Max = max(Max, max(arr[a][i].max,arr[b][i].max)); Min = min(Min, min(arr[a][i].min, arr[b][i].min)); a = arr[a][i].to; b = arr[b][i].to; } Max = max(Max, max(arr[a][0].max, arr[b][0].max)); Min = min(Min, min(arr[a][0].min, arr[b][0].min)); } printf("%d %d\n", Min, Max); } int main() { scanf("%d", &N); H = ceil(log2(N)); list.resize(N + 1); h[1] = 1; for (int i = 0; i < N - 1; i++) { int a, b, dist; scanf("%d %d %d", &a, &b, &dist); list[a].push_back({ b,dist,dist }); list[b].push_back({ a,dist,dist }); } dfs(1); makeTree(); scanf("%d", &K); for (int i = 0; i < K; i++) { int a, b; scanf("%d %d", &a, &b); Dist(a, b); } } | cs |
반응형
'백준' 카테고리의 다른 글
[ 백준 ] 1153번 - 길의 개수 (C++) (0) | 2022.08.24 |
---|---|
[ 백준 ] 11286번 - 절댓값 힙 (C++) (0) | 2022.08.23 |
[ 백준 ] 1780번 - 종이의 개수 (C++) (0) | 2022.08.21 |
[ 백준 ] 1931번 - 회의실 배정 (C++) (0) | 2022.08.20 |
[ 백준 ] 11047번 - 동전 0 (C++) (0) | 2022.08.19 |