hyelie
hyelie
Hyeil Jeong
       
글쓰기    관리    수식입력
  • 전체보기 (495)
    • PS (283)
      • Algorithm (28)
      • PS Log (244)
      • Contest (6)
      • Tips (5)
    • Development (52)
      • Java (14)
      • Spring (23)
      • SQL (2)
      • Node.js (2)
      • Socket.io (3)
      • Study (4)
      • Utils (4)
    • DevOps (36)
      • Git (5)
      • Docker (4)
      • Kubernetes (2)
      • GCP (3)
      • Environment Set Up (8)
      • Tutorial (12)
      • Figma (2)
    • CS (74)
      • OOP (7)
      • OS (24)
      • DB (2)
      • Network (24)
      • Architecture (0)
      • Security (2)
      • Software Design (0)
      • Parallel Computing (15)
    • Project (15)
      • Project N2T (5)
      • Project ASG (0)
      • Project Meerkat (1)
      • Model Checking (7)
      • Ideas (2)
    • 내가 하고싶은 것! (34)
      • Plan (16)
      • Software Maestro (10)
      • 취준 (8)
hELLO · Designed By 정상우.
hyelie

hyelie

PS/PS Log

23.04.29. 풀었던 문제들

1697. Checking Existence of Edge Length Limited Paths

 edge 간 weight가 있는 어떤 graph와 [vertex 1, vertex 2, limit]으로 주어지는 query list가 있을 때 각 query의 vertex 1부터 vertex 2까지 path 중 max값이 limit보다 작으면 true를, 아니면 false를 계산하는 문제. vertex 개수를 V, edge 개수를 E, query 개수를 Q라고 했을 때 0 <= V, E, Q <= 100,000이기 때문에 nlogn 이하로 풀어야 한다.

  • limit을 기준으로 queries, edgeList 오름차순 정렬
  • union-find를 이용하면 어떤 두 vertex가 이어져있는지 아닌지 쉽게 알 수 있다.(root를 찾고, 같다면 이어져 있는 것) 이 특징을 이용한다.
  • 모든 query에 대해 아래 사항을 반복한다.
    • 어떤 query의 limit보다 작은 모든 edge weight를 union한다.
    • 그 결과로 해당 query limit보다 작은 모든 edge들이 union되며, 이 때 query가 가지고 있는 vertex 1과 vertex 2의 root가 같으면 query limit보다 작은 edge들로 두 vertex가 이어진다. 아닌 경우 이어지지 않는다.
// Runtime 652 ms Beats 48.55%
// Memory 110.1 MB Beats 78.84%

bool cmp(vector<int>& a, vector<int>& b){
    if(a[2] < b[2]) return true;
    else return false;
}

class Solution {
public:
    vector<int> parent, rank;
    void makeDS(int n){
        parent.resize(n);
        for(int i = 0; i<n; i++) parent[i] = i;
        rank.resize(n, 0);
    }

    int find(int x){
        if(x == parent[x]) return x;
        parent[x] = find(parent[x]);
        return parent[x];
    }

    void join(int x, int y){
        int rx = find(x), ry = find(y);

        if(rank[rx] > rank[ry]){ // ry가 rx 아래로 들어감
            parent[ry] = rx;
        }
        else{
            if(rank[rx] == rank[ry]){
                rank[ry]++;
            }
            parent[rx] = ry;
        }
    }

    vector<bool> distanceLimitedPathsExist(int n, vector<vector<int>>& edgeList, vector<vector<int>>& queries) {
        for(int i = 0; i<queries.size(); i++){
            queries[i].push_back(i); // index 추가
        }

        // limit 오름차순 정렬
        sort(queries.begin(), queries.end(), cmp);
        sort(edgeList.begin(), edgeList.end(), cmp);

        makeDS(n);
        int i = 0;
        vector<bool> answer(queries.size(), false);
        for(vector<int>& query : queries){
            int limit = query[2];
            for(; i < edgeList.size() && edgeList[i][2] < limit; i++) join(edgeList[i][0], edgeList[i][1]);

            int x = query[0], y = query[1], originIdx = query[3];
            if(find(x) == find(y)) answer[originIdx] = true;
        }
        
        return answer;
    }
};

 

시간복잡도

 2중 for문이라 O(Q * E)가 나올 것 같지만, 실제로는 edgeList를 1번, queries를 1번 순회하며, edgeList를 순회하며 disjoint set을 union하기 때문에 O(Q + Elog*V)이다.

 

공간복잡도

 rank, parent vector는 size V, answer vector는 size Q이기 때문에 O(V + Q)이다.

 

후기

 나중에 다시 풀어보자... 어렵다.

 두 vertex의 연결 여부를 판단하기 위해서 union-find를 사용할 수 있다. 기억해 두자.

 

 

 

 

저작자표시 (새창열림)

'PS > PS Log' 카테고리의 다른 글

23.05.01. 풀었던 문제들  (0) 2023.05.01
23.04.30. 풀었던 문제들  (0) 2023.04.30
23.04.28. 풀었던 문제들  (0) 2023.04.28
23.04.27. 풀었던 문제들  (0) 2023.04.27
23.04.26. 풀었던 문제들  (0) 2023.04.26
    hyelie
    hyelie

    티스토리툴바