UVA 10305 Ordering Tasks

拓扑排序的模板题,主要是来学习一下用DFS来判断是否有环,以及输出拓扑排序的序列。用DFS进行拓扑排序需要借助一个标记c[v]c[v]=0表示图中的结点未被访问过,c[v]=1表示正在访问结点(及其后继),c[v]=2表示结点访问完成。(当然,也可以设置为其他有相同含义的不同的数值。)

有向图中存在环,当且仅当访问到一个结点vc[v]=1。证:设当前正在访问结点u,其直接后继v满足c[v]=1,那么一定存在一条从vu的路径,又存在有向边(u,v),则图中存在环。若c[v]!=1,那么不存在从vu的路径,也就没有环。

另一种比较熟悉的做法是不断从图中删去入度为0的结点,并把其加入拓扑序列。如果图中剩余的所有结点都不满足入度为0,则说明图中存在环。

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
47
48
49
50
51
52
#include <bits/stdc++.h>

using namespace std;

const int MAX_V = 100 + 5;

int n, m;
vector<int> G[MAX_V];
int c[MAX_V];
int seq[MAX_V], idx;

bool dfs(int v) {
c[v] = 1; // accessing
for (int i = 0; i < G[v].size(); i++) {
int u = G[v][i];
if (c[u] == 1) return false;
else if (c[u] == 0 && !dfs(u)) return false;
}
c[v] = 2; // accessed
seq[idx--] = v; // v should be before all its successor
return true;
}

bool toposort() {
memset(c, 0, sizeof(c));
idx = n - 1;
for (int v = 1; v <= n; v++) {
if (c[v] == 0 && !dfs(v))
return false;
}
return true;
}

int main() {
while (scanf("%d %d", &n, &m) && (n || m)) {
for (int v = 1; v <= n; v++) G[v].clear();
for (int i = 0; i < m; i++) {
int u, v;
scanf("%d %d", &u, &v);
G[u].push_back(v);
}

if (toposort()) {
for (int i = 0; i < n; i++) {
printf("%d%c", seq[i], i == n - 1 ? '\n' : ' ');
}
} else {
// do something
}
}
return 0;
}
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
#include <bits/stdc++.h>

using namespace std;

const int MAX_V = 100 + 5;

int n, m;
vector<int> G[MAX_V];
int indeg[MAX_V];

int main() {
while (scanf("%d %d", &n, &m) && (n || m)) {
for (int v = 1; v <= n; v++) G[v].clear();
memset(indeg, 0, sizeof(indeg));
for (int i = 0; i < m; i++) {
int u, v;
scanf("%d %d", &u, &v);
G[u].push_back(v);
indeg[v]++;
}
queue<int> que;
for (int v = 1; v <= n; v++) {
if (indeg[v] == 0) que.push(v);
}
vector<int> ans;
while (!que.empty()) {
int v = que.front(); que.pop();
ans.push_back(v);
for (int i = 0; i < G[v].size(); i++) {
int u = G[v][i];
indeg[u]--;
if (indeg[u] == 0) que.push(u);
}
}
for (int i = 0; i < ans.size(); i++) {
printf("%d%c", ans[i], i == ans.size() - 1 ? '\n' : ' ');
}
}
return 0;
}