BOJ 2252 - 줄 세우기
문제
- \(N(1 \le N \le 32000),\; M(1\le M \le 100000)\)이 주어진다.
- \(N\)개의 정점에 대해 \(M\) 개의 단방향 간선이 주어질 때, 위상 정렬의 경우의 수 중 하나를 출력해야 한다.
풀이
- In-degree, DFS를 사용하는 방법을 모두 구현해서 실행 시간을 비교해보았다.
In-degree
ind[n]
배열에 각 정점의 in-degree 정보를 저장한다.ind[i]==0
인i
들을 큐q
에 추가한다.!q.empty()
일 동안 아래 과정을 반복한다.q
에서v=dequeue()
하며 front였던 정점v
를res
리스트에 추가한다.v
에 대해v x
관계인x
의ind[x]
를 1씩 감소한다.
이떄ind[x]
가 0이되면enqueue(x)
를 실행한다.
res
가 위상 정렬 결과이다.
In-degree 코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include <iostream>
#include <queue>
#include <vector>
#define v vector
using namespace std;
using vi = vector<int>;
// in-degree
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int n, m;
cin >> n >> m;
vi ind(n, 0), ans;
v<vi> adj(n, vi(0));
queue<int> q;
for (int i = 0; i < m; i++) {
int s, e;
cin >> s >> e;
s--, e--;
adj[s].push_back(e);
ind[e]++;
}
for (int i = 0; i < n; i++) {
if (ind[i] == 0) {
q.push(i);
}
}
while (!q.empty()) {
int cur = q.front();
q.pop();
ans.push_back(cur + 1);
for (int i = 0; i < adj[cur].size(); i++) {
int nv = adj[cur][i];
ind[nv]--;
if (ind[nv] == 0) {
q.push(nv);
}
}
}
for (int i = 0; i < ans.size(); i++) {
cout << ans[i] << ' ';
}
return 0;
}
DFS
vis[n]
에 정점의 방문 여부를 저장한다.vis[i]==0
인 정점i
에 대해 아래 과정의 DFS(i)를 실행한다.vis[i]=1
i x
관계에 대해vis[x]==0
이면 DFS(x) 실행res
리스트의 첫 부분에i
추가
res
가 위상 정렬 결과이다.
DFS 코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include <algorithm>
#include <iostream>
#include <vector>
#define v vector
using namespace std;
using vi = vector<int>;
// DFS
int tpsort(v<vi> &adj, vi &vis, int v, vi &tv) {
vis[v] = 1;
for (int i = 0; i < adj[v].size(); i++) {
int nv = adj[v][i];
if (vis[nv] == 0)
tpsort(adj, vis, nv, tv);
}
tv.push_back(v);
return 0;
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int n, m;
cin >> n >> m;
vi vis(n, 0), ans;
v<vi> adj(n, vi(0));
for (int i = 0; i < m; i++) {
int t1, t2;
cin >> t1 >> t2;
adj[t1 - 1].push_back(t2 - 1);
}
for (int i = 0; i < n; i++) {
if (vis[i] == 0) {
tpsort(adj, vis, i, ans);
}
}
reverse(ans.begin(), ans.end());
for (int i = 0; i < ans.size(); i++)
cout << ans[i] + 1 << ' ';
return 0;
}
풀고나서
- 두 방법에 대한 채점 결과는 아래 표와 같다.
방법 | 메모리 | 시간 |
---|---|---|
In-degree | 4220KB |
24ms |
DFS | 4216KB |
28ms |
- 메모리 차이는 크게 없지만, In-degree가 실행 속도가 미세하게 더 빠르다.
- DFS의 재귀 호출의 영향이라 짐작된다.
Leave a comment