-
[백준]1167 - 트리의 지름 (DFS)코테/백준 2023. 2. 24. 04:02
https://www.acmicpc.net/problem/1167
1167번: 트리의 지름
트리가 입력으로 주어진다. 먼저 첫 번째 줄에서는 트리의 정점의 개수 V가 주어지고 (2 ≤ V ≤ 100,000)둘째 줄부터 V개의 줄에 걸쳐 간선의 정보가 다음과 같이 주어진다. 정점 번호는 1부터 V까지
www.acmicpc.net
정점과 각 정점간의 거리가 주어졌을때
가장 긴 두 정점 사이의 거리를 구하는 문제
각 정점들을 시작점으로 dfs 탐색을 해 최대값을 구하면 쉽게 풀리지만,
정점이 촤대 10만개라 시간 초과가 발생한다
-> a 점을 시작으로 최대거리와 그때의 도착점 b를 구하고
다시 b를 시작점으로 최대거리를 구했을때 도착점이 a면 해당 거리가 최대 거리가 된다
예제 입력
int N; cin >> N; v = vector<vector<pair<int,int>>>(N+1); while (N--) { int n; cin >> n; int a, b; while (1) { cin >> a; if (a == -1) break; cin >> b; if (a > n) { v[n].push_back({ a,b }); v[a].push_back({ n,b });
v[3]은 3번 점과 연결된 1번점과 4번점, 그리고 해당 점까지의 거리인 {1,2} {4,3}을 지니게 된다
int start = 1; visit[start] = 1; dfs(start); while(1) { counts = 0; for (int j = 0; j < 100000; j++) visit[j] = 0; visit[maxa] = 1; dfs(maxa); if (maxa == start) { cout << answer; return 0; } start = maxa; }
임의의 점 1을 기준으로 dfs를 돌리고 최대거리(answer)와 그떄의 도착점(maxa)를 구함
이후 maxa를 기준으로 다시 탐색을 돌려 도착점이 시작점이면 값을 출력,
아니면 start에 maxa를 넣고 다시 탐색
void dfs(int i) { for (int k = 0; k < v[i].size(); k++) { int node = v[i][k].first; int gap = v[i][k].second;
dfs 탐색
매개변수로 시작점을 받고
for문으로 시작점에 연결된 정점들과 거리를 node, gap에 저장
if (visit[node] != 1) { visit[node] = 1; counts += gap; if (counts > answer) { maxa = node; answer = counts; } dfs(node); counts -= gap; visit[node] = 0;
방문하지 않은 정점이면
방문했단 표시를 하고 누적 거리에 +
누적거리가 answer보다 크면 answer를 해당 값으로 = 최대 누적거리가 answer에 저장
이후 dfs 탐색을 재귀적으로 반복
dfs() 아래의 코드는 dfs 탐색후 되돌아오는 것이므로 counts와 visit를 다시 원래대로
#include <vector> #include <iostream> using namespace std; void dfs(int i); int visit[100001]; int answer = -1; int counts = 0; int maxa; vector<vector<pair<int, int>>> v; int main() { ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL); int N; cin >> N; v = vector<vector<pair<int,int>>>(N+1); while (N--) { int n; cin >> n; int a, b; while (1) { cin >> a; if (a == -1) break; cin >> b; if (a > n) { v[n].push_back({ a,b }); v[a].push_back({ n,b }); } } } int start = 1; visit[start] = 1; dfs(start); while(1) { counts = 0; for (int j = 0; j < 100000; j++) visit[j] = 0; visit[maxa] = 1; dfs(maxa); if (maxa == start) { cout << answer; return 0; } start = maxa; } return 0; } void dfs(int i) { for (int k = 0; k < v[i].size(); k++) { int node = v[i][k].first; int gap = v[i][k].second; if (visit[node] != 1) { visit[node] = 1; counts += gap; if (counts > answer) { maxa = node; answer = counts; } dfs(node); counts -= gap; visit[node] = 0; } } }
전체 코드
'코테 > 백준' 카테고리의 다른 글
[백준]16506 - CPU (0) 2023.06.19 [백준]3568 - iSharp (구현) (0) 2023.06.19 [백준]14500 - 테르로미노 (0) 2023.03.02 [백준]10818 - 최댓값 최솟값 (0) 2023.02.24 [백준]2609 - 최대공약수와 최소공배수 (0) 2023.02.24