백준 1761번: 정점들의 거리
문제
문제 바록가기> 백준 1761번: 정점들의 거리
풀이
2^k번째 node까지의 조상과 거리의 합을 저장해놓고, LCA를 이용해서 문제를 풀었다.
자세한 내용은 주석을 참고하자!
#include<iostream>
#include<algorithm>
#include<vector>
#define MAX_N 40001
#define MAX_K 16
using namespace std;
struct Data{int end, dist;};
int N, M;
int depth[MAX_N]; // 노드의 depth 저장
bool visit[MAX_N]; // dfs 탐색 시 방문 여부 체크
int dp[MAX_N][MAX_K]; // 2^k번째 조상까지 저장
int dpDist[MAX_N][MAX_K]; // 거리의 합 정보 저장
vector<Data> tree[MAX_N]; // tree의 정보 저장
void dfs(int n, int d){
depth[n] = d; // depth 저장
visit[n] = true; // 방문
for(int i=0; i<tree[n].size(); i++){
int next = tree[n][i].end; // 다음 방문할 node
int dist = tree[n][i].dist; // 다음 node 까지의 거리
if(visit[next]) continue; // 이미 방문한 경우
dp[next][0] = n; // 부모 정보 저장
dpDist[next][0] = dist; // 거리 정보 저장
dfs(next, d+1); // dfs 탐색
}
}
void init(){ // 2^k번째 조상까지의 정보 저장
for(int i=1; i<MAX_K; i++){
for(int j=1; j<=N; j++){
dp[j][i] = dp[dp[j][i-1]][i-1]; // node
dpDist[j][i] = dpDist[j][i-1] + dpDist[dp[j][i-1]][i-1]; // dist
}
}
}
int lca(int x, int y){ // 두 node간의 거리 반환
int ans = 0;
if(depth[y]<depth[x]) swap(x, y); // y가 더 깊음을 보장
for(int i=MAX_K-1; i>=0; i--){ // x, y의 depth를 맞춤
if(depth[y]-depth[x] >= 1<<i){
ans+=dpDist[y][i];
y = dp[y][i];
}
}
if(x==y) return ans; // x가 LCA(최소 공통 조상)인 경우
for(int i=MAX_K-1; i>=0; i--){ // lca를 가지기 위해
if(dp[x][i]!=dp[y][i]){
ans+=dpDist[x][i];
ans+=dpDist[y][i];
x = dp[x][i];
y = dp[y][i];
}
}
ans+=(dpDist[x][0]+dpDist[y][0]);
return ans;
}
int main(){
ios_base::sync_with_stdio(0); cin.tie(0);
cin >> N;
int s, e, d;
for(int i=0; i<N-1; i++){ // tree를 만듦
cin >> s >> e >> d;
tree[s].push_back({e, d});
tree[e].push_back({s, d}); // tree는 양방향
}
dfs(1, 0); // 거리, 부모노드 정보 저장
init(); // 2^k번째 조상까지의 정보 저장
cin >> M;
for(int i=0; i<M; i++){
cin >> s >> e;
cout << lca(s, e) << '\n';
}
}
Author And Source
이 문제에 관하여(백준 1761번: 정점들의 거리), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@danbibibi/백준-1761번-정점들의-거리저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)