Uva--10305 Ordering Tasks(拓扑排序)
记录
15:42 2023-5-26
reference:《算法竞赛入门经典第二版》例题6-15
拓扑排序
一种是书上利用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");
}
}
}