1. 위상정렬(Topological Sort)이란?
방향 그래프에서 선후관계에 따라 적절한 순서를 찾는 알고리즘
전체 순서가 아닌 일부 순서가 주어진 경우 여러가지 경우로 줄을 세울 수 있다
-문제 유형
어떤 작업ㄷ르에 대한 순서가 주어졌을 때
자신보다 선행되어야 할 일을 다 끝내야 작업에 들어갈 수 있게 주어졌을 때
2. 동작 원리
방향은 존재하지만 사이클은 존재해선 안 된다. (순서를 명확히 정할 수 없기 때문)
-bfs 방식 위상정렬
indegree가 0인 노드를 큐에 넣어준다
큐의 front(현재 정점)을 방문한다
front()에 연결되어있는 다음 정점들을 방문하고 indegree[next]를 1씩 감소시킨다
감소시켰을 때 indegree가 0이라면 큐에 넣어준다
-dfs 방식 위상정렬
방문하지 않은 점점에서 dfs시작
탐색이 끝나면 그 정점을 스택(벡터)에 넣는다
탐색 종료 후 스택에 쌓은 것을 출력한 순서가 위상정렬
3. 코드
//BFS 방식 위상정렬
while (M--) {
int a, b;
cin >> a >> b;
adj[a].push_back(b);
indegree[b]++;
}
queue<int> q;
for (int i = 1; i <= N; i++) {
if (!indegree[i]) { //indegree가 0인 정점 큐에 삽입
q.push(i);
ans.push_back(i);
}
}
while (!q.empty()) {
int now = q.front();
q.pop();
for (auto next : adj[now]) {
indegree[next]--;
if (indegree[next] == 0) {
q.push(next);
ans.push_back(next);
}
}
}
if (ans.size() != N) {
printf("사이클 존재");
return 0;
}
//BFS 방식 위상정렬 사이클 찾기2
for (int i = 0; i < N; i++) {
if (q.empty()) {
printf("사이클 존재");
return 0;
}
int now = q.front();
q.pop();
for (auto next : adj[now]) {
indegree[next]--;
if (indegree[next] == 0) {
q.push(next);
ans.push_back(next);
}
}
}
//DFS 방식 위상정렬
stack<int> s;
int visited[32001]; //0: 미방문, 1: 방문중, 2: 방문완료
vector<int> adj[32001];
void dfs(int now) {
visited[now] = 1;
for (auto next : adj[now]) {
if (visited[next] == 0) {
dfs(next);
}
else if (visited[next] == 1) {
printf("사이클 존재");
return;
}
}
visited[now] = 2;
s.push(now);
}
int main() {
cin >> N >> M;
while (M--) {
int a, b;
cin >> a >> b;
adj[a].push_back(b);
}
for (int i = 0; i < N; i++) {
if (!visited[i]) {
dfs(i);
}
}
while (s.size()) {
printf("%d ", s.top());
}
}
※공부 중 작성한 내용이기에 틀린 부분이 있을 수도 있습니다!
728x90
반응형
'🔻Extracurricular Activity > ALCUK' 카테고리의 다른 글
[2022 1학기] 11주차 - MST (0) | 2022.05.15 |
---|---|
[2022 1학기] 10주차 - 유니온-파인드 (0) | 2022.05.04 |
[2022 겨울학기] 8주차 - 자료구조(스택, 큐) (0) | 2022.04.10 |
[2022 겨울학기] 7주차 - 이분탐색 (0) | 2022.04.10 |
[2022 겨울학기] 5주차 - 다이나믹 프로그래밍 (0) | 2022.04.10 |