4단계는 어려운거같다...
코드를 봐도 cycle을 의미한다하여 응? 왜 그게 cycle을 의미하는건데? 근본적인 질문이 떠오르고
내 방식대로 하려하면 왠지 너무 복잡해진다. 근데 대부분의 답은 내 방식대로 한게 맞는거같다..
검색하다가 위상정렬(topology sort)라는 것을 알게됐다.
(이 해설에 들어갔다가 알게됨 : https://2jinishappy.tistory.com/200, 풀이는 참고하지 않았고, 검색해서 찾아낸 위상 정렬을 설명해주고있는 아래 참고 링크에서 sort 원리만 참고했다.)
다른 방법들도 있는것 같았지만, 이게 제일 명확했다.
#include <string>
#include <vector>
#include <queue>
using namespace std;
bool topology_sort(vector<vector<int>>& di, vector<int>& indegree){
queue<int> que;
que.push(0);
for(int i=0; i<di.size(); i++){
if(que.empty()) return false; // cycle 발생
int room = que.front(); que.pop();
for(auto to : di[room]){
if(--indegree[to] == 0) que.push(to);
}
}
return true;
}
bool solution(int n, vector<vector<int>> path, vector<vector<int>> order) {
vector<vector<int>> undirected(n);
for(auto p: path){
undirected[p[0]].push_back(p[1]);
undirected[p[1]].push_back(p[0]);
}
vector<vector<int>> directed(n);
vector<int> indegree(n, 0); indegree[0] = 0;
queue<int> que; que.push(0);
vector<bool> visit(n, false); visit[0] = true;
while(!que.empty()){
int room = que.front(); que.pop();
for(auto to : undirected[room]){
if(visit[to]) continue;
que.push(to);
directed[room].push_back(to);
visit[to] = true;
indegree[to]++;
}
}
for(auto o: order){
if(o[1] == 0) return false;
directed[o[0]].push_back(o[1]); // o[0]을 방문한 뒤 o[1]을 감
indegree[o[1]]++;
}
return topology_sort(directed, indegree); // learned
}
문제
https://programmers.co.kr/learn/courses/30/lessons/67260
코딩테스트 연습 - 동굴 탐험
9 [[0,1],[0,3],[0,7],[8,1],[3,6],[1,2],[4,7],[7,5]] [[8,5],[6,7],[4,1]] true 9 [[8,1],[0,1],[1,2],[0,7],[4,7],[0,3],[7,5],[3,6]] [[4,1],[5,2]] true 9 [[0,1],[0,3],[0,7],[8,1],[3,6],[1,2],[4,7],[7,5]] [[4,1],[8,7],[6,5]] false
programmers.co.kr
[접근]
topology sort(링크 추가 예정)
참고: https://m.blog.naver.com/ndb796/221236874984
BFS
https://jolly-note.tistory.com/63
BFS (Breadth First Search, 너비 우선 탐색)
접근 graph 또는 tree를 탐색하는 알고리즘이다. 특정 노드부터 시작하여 인접한 노드들을 먼저 탐색한다. (최단 경로를 찾을 때 사용) 특정 노드로부터의 거리에 따라 순서대로 탐색한다. 알고리
jolly-note.tistory.com
[접근1]
우선 서로 가리키는 graph를 만들고,
그것을 바탕으로 한쪽 방향으로 graph를 만든다.
거기에 order를 추가하여 cycle의 여부를 판단할 수 있게 한다.
vector<vector<int>> undirected(n);
for(auto p: path){
undirected[p[0]].push_back(p[1]);
undirected[p[1]].push_back(p[0]);
}
vector<vector<int>> directed(n);
vector<int> indegree(n, 0); indegree[0] = 0;
queue<int> que; que.push(0);
vector<bool> visit(n, false); visit[0] = true;
while(!que.empty()){
int room = que.front(); que.pop();
for(auto to : undirected[room]){
if(visit[to]) continue;
que.push(to);
directed[room].push_back(to);
visit[to] = true;
indegree[to]++;
}
}
for(auto o: order){
if(o[1] == 0) return false;
directed[o[0]].push_back(o[1]); // o[0]을 방문한 뒤 o[1]을 감
indegree[o[1]]++;
}
indegree란, 앞의 참고 링크에서 볼 수 있듯, 해당 노드를 가리키는 노드의 수라고 할 수 있다.
[접근2]
topology sort를 해준다.
만약 n번을 다 돌기 전에 queue가 비었다면, 모든 노드를 돌지 않았다는것이므로 false를 리턴해준다.
node를 하나씩 빼면서 이어진 선들을 다 제거한다. 이어져있는 node의 indegree를 1씩 줄이면서 나타낼 수 있다.
이어져 있는 노드를 가리키는 노드가 더이상 없을 때, que에 집어넣는다.
n번을 다 돌때까지 queue가 비지 않는다면 true이다.
bool topology_sort(vector<vector<int>>& di, vector<int>& indegree){
queue<int> que;
que.push(0);
for(int i=0; i<di.size(); i++){
if(que.empty()) return false; // cycle 발생
int room = que.front(); que.pop();
for(auto to : di[room]){
if(--indegree[to] == 0) que.push(to);
}
}
return true;
}'coding > algorithm' 카테고리의 다른 글
| [programmers] Lv.2 카카오프렌즈 컬러링북(c++) (0) | 2022.05.06 |
|---|---|
| [programmers] Lv.3 징검다리 건너기(c++) (0) | 2022.05.05 |
| [programmers] Lv.3 불량 사용자(c++) (0) | 2022.05.04 |
| [programmers] Lv.2 튜플(c++) (0) | 2022.05.04 |
| [programmers] Lv.3 경주로 건설(c++) (0) | 2022.05.03 |
댓글