记录
15:42 2023-5-26
https://onlinejudge.org/external/103/p10305.pdf
reference:《算法竞赛入门经典第二版》例题6-15
拓扑排序,存在有向环的图没有解。不包含有向环的有向图称为有向无环图(Directed Acyclic Graph,DAG)
书上给出来的是使用dfs方式进行拓扑排序,注意访问状态visited[]数组的使用,如果dfs途中又访问了已经正在访问的节点,说明是存在回路。
另一种方式是我之前学过的,《数据结构与算法分析》中的拓扑排序,类似于bfs的方法,加入队列是入度为0的节点,从队列中取出一个节点后,更新其它节点的入度并将入度为0的点再放入队列。
使用dfs
#include<cstdio>
#include<cstring>
#define MAX_N 1000
using namespace std;
typedef long long ll;
typedef unsigned int uint;
const int INF = 0x3f3f3f3f;
int G[MAX_N][MAX_N];
int visited[MAX_N]; // 0表示未访问 1表示访问过 -1表示正在访问
int tops[MAX_N];
int t;
int N, M;
bool dfs(int u) {
visited[u] = -1;
for(int i = 1; i <= N; i++) {
if(G[u][i]) {
//i访问到正在访问的节点 表示有回环
if(visited[i] == -1) return false;
else if(!visited[i] && !dfs(i)) return false;
}
}
visited[u] = 1;
tops[t--] = u;
return true;
}
bool solve() {
t = N;
memset(visited, 0, sizeof(visited));
for(int i = 1; i <= N; i++) {
if(!visited[i]){
if(!dfs(i)) return false;
}
}
return true;
}
int main () {
while (scanf("%d%d", &N, &M) == 2 && N) {
memset(G, 0, sizeof(G));
int s, e;
for(int i = 0; i < M; i++) {
scanf("%d%d", &s, &e);
G[s][e] = 1;
}
if(solve()) {
for(int i = 1; i < N; i++) {
printf("%d ", tops[i]);
}
printf("%d\n", tops[N]);
} else {
printf("No\n");
}
}
}
使用类bfs
#include<cstdio>
#include<cstring>
#include<queue>
#define MAX_N 1000
using namespace std;
typedef long long ll;
typedef unsigned int uint;
const int INF = 0x3f3f3f3f;
int G[MAX_N][MAX_N];
int indegree[MAX_N];
int tops[MAX_N];
int t = 1;
int count = 0;
int N, M;
queue<int> q;
bool topsort() {
for(int i = 1; i <= N; i++) {
if(indegree[i] == 0) {
q.push(i);
count++;
}
}
while (!q.empty()) {
int u = q.front();q.pop();
tops[t++] = u;
for(int i = 1; i <= N; i++) {
if(G[u][i]) {
if(--indegree[i] == 0) {
q.push(i);
count++;
}
}
}
}
if(count != N) return false;
return true;
}
int main () {
while (scanf("%d%d", &N, &M) == 2 && N) {
memset(G, 0, sizeof(G));
memset(indegree, 0, sizeof(indegree));
count = 0;
t = 1;
int s, e;
for(int i = 0; i < M; i++) {
scanf("%d%d", &s, &e);
G[s][e] = 1;
indegree[e]++;
}
if(topsort()) {
for(int i = 1; i < N; i++) {
printf("%d ", tops[i]);
}
printf("%d\n", tops[N]);
} else {
printf("No\n");
}
}
}