백준(boj)6059 - Pasture Walking

업데이트:

문제 링크 - https://www.acmicpc.net/problem/6059

👀문제이해 및 풀이방법

가장 전형적인 트리 lca문제이다. 트리의 간선마다 길이가 있고 두 정점의 거리를 구하는 문제이다.
2차원 dis배열을 사용해서 두 정점간의 거리를 양방향 모두 입력해 둔다 이를 통해서 root를 1로 정해서 maketree를 통해 트리를 만들며 각 node마다 부모 node와 깊이, root와의 거리를 저장했다.
이후 두 정점의 depth를 통해 lca를 찾아 두 정점이 가진 root와의 거리의 합에서 lca의 root와의 거리*2를 빼주면 답이 나온다 처음에 *2를 안해서 틀렸었다.😥
트리 문제중 꼭 풀어봐야하는 문제중 하나라고 생각한다.

📝코드

#include <iostream>
#include <vector>
using namespace std;
struct _node{
    int parent;
    int depth;
    int dis;
};
class walking{
private:
    vector<_node> tree;
    vector<vector<int>> dis;
    int N,Q;
public:
    walking(){
        std::cin >> N >> Q;
        tree.resize(N+1,{0,0,});
        dis.resize(N+1,vector<int>(N+1,0));
        set_connect();
        maketree(1,0,1,0);
    }
    void set_connect(){
        int a,b,d;
        for(int i=1;i<N;i++){
            std::cin >>a >> b>> d;
            dis[a][b]=d;
            dis[b][a]=d;
        }
    }
    void maketree(int cur,int parent,int depth,int d){
        tree[cur].parent=parent;
        tree[cur].depth=depth;
        tree[cur].dis=d;
        for(int i=1;i<=N;i++)
            if(dis[cur][i] && i!=parent)
                maketree(i,cur,depth+1,d+dis[cur][i]);
    }
    int lca(int a,int b){
        int sol = tree[a].dis+tree[b].dis;
        if(tree[a].depth>tree[b].depth)
            swap(a,b);
        while(tree[a].depth!=tree[b].depth)
            b=tree[b].parent;
        if(a==b)
            return sol-tree[a].dis*2;
        while(a!=b){
            a=tree[a].parent;
            b=tree[b].parent;
        }
        return sol-tree[a].dis*2;
    }
    void find_sol(){
        int a,b;
        for(int i=0;i<Q;i++){
            std::cin >> a >> b;
            std::cout << lca(a,b) << '\n';   
        }
    }
};
int main(){
    cin.tie(NULL);cout.tie(NULL);
    ios_base::sync_with_stdio(false);
    walking wk;
    wk.find_sol();
    return 0;
}

image

댓글남기기