2가지 기준을 만족해야 함.

1. beforeItems가 나타내는, item간 선후관계

2. 같은 그룹 내 원소들은 항상 인접하게

 

1은 topology sort 사용하면 되는게 바로 보이는데, 1을 만족하면서 동시에 2를 만족하려면?

→ 2가 만족하려면, 그룹별로도 1을 만족하도록 위상정렬이 되야함.

1에 따라 그룹 간 dependency 구한다음 위상정렬; 그 후 각 그룹 내 원소간 dependency에 따라 그룹별로 다시 위상정렬 (Two-level topology sort)

 

아이디어가 익숙하지 않아서 생각하지 못함.

설령 떠올린다 하더라도, 구현하는데 막막함.

 

https://leetcode.com/problems/sort-items-by-groups-respecting-dependencies/discuss/387977/Python-Use-DFS-to-%22detect-cycle%22-(like-210.-Course-Schedule-II-and-269.-Alien-Dictionary)

이 코드를 참고해서 C++로 구현했음.

 


1] 가장 먼저 dependency를 표현할 자료구조

map<int, map<int,vi>> graph_items; // key : group | value : dependency within the same group (key : node | val : dependency vector)
map<int, set<int>> graph_group; // graph between groups

graph_group[1] { 2, 3, 4 } 라고 하면, 그룹 1 -> 2, 3, 4 라는 관계가 있다는 뜻.

 

graph_items는 그룹 G : 그룹 G내 원소들간의 dependency graph 를 담고있는 map

만약 Groupt 1에 2, 3, 4, 5 라는 원소가 있고, 2 -> 3, 4, 5 / 3 -> 5 라는 관계가 있다면 다음과 같이 표현됨

graph_items[1] = {2 : {3, 4, 5}, 3 : {5} } 

 

Q. 왜 map을 이용해서 이렇게 복잡하게 짰나? vector 쓰면?

-> 각 그룹에 어떤 node가 들어갈 지 모르니까, vector 쓰면 size N allocation 해야함. 비효율적이라고 생각.

 

2] topology_sort와 dfs

group graph나 item graph 중 뭐가 와도 작동할 수 있도록 template 이용해서 짬(이렇게 통일하려고 graph_group도 map을 씀)

 

★ 특히 DFS에서 cycle detection - 3-color 방법 씀

https://www.geeksforgeeks.org/detect-cycle-direct-graph-using-colors/

 

Detect Cycle in a directed graph using colors - GeeksforGeeks

A Computer Science portal for geeks. It contains well written, well thought and well explained computer science and programming articles, quizzes and practice/competitive programming/company interview Questions.

www.geeksforgeeks.org

Gray - visited, 아직 dfs안끝남 

만약 현재 노드에서 gray 노드로 이어지는 간선이 있다면? = back edge = cycle

// Visit each node using DFS + return true if there exists back edge (cycle detection)
template <class T>
bool dfs(int node, map<int, T>& graph, vi& order) {
    visited[node] = GRAY;
    for (int nxt : graph[node]) {
        if (visited[nxt] == GRAY)
            return true;

        if (visited[nxt] == WHITE && dfs(nxt, graph, order))
            return true;
    }
    visited[node] = BLACK;
    order.push_back(node);
    return false;
}

// Used in both step 2 (graph sort) and step 3 (items sort)
// T : vector<int> or set<int>
template <class T>
vi topology_sort(map<int, T>& graph) {
    vi order;

    // DFS on each graph element
    for(auto it = graph.begin(); it != graph.end(); it++){
        if (!visited[it->first])
            if (dfs(it->first, graph, order)) {
                cycleDetected = true;
                return vi();
            }
    }
    reverse(all(order));
    return order;
}

 

이렇게 짜두니까 나머지 위상 정렬은 코드 매우 간단해짐

Step 2 - group 위상정렬

Step 3 - 각 group별 items graph 넣어줘서 위상정렬 (총 그룹 개수 m번 반복)

 

 

공부한 점 : 그래프를 표현하는 복잡한 자료구조, cycle detection, 코드 모듈화 (재활용), 위상 정렬

 

 

+ Recent posts