10305 - Ordering Tasks

Ordering Tasks

John has n tasks to do. Unfortunately, the tasks are not independent and the execution of one task is only possible if other tasks have already been executed.

Input

The input will consist of several instances of the problem. Each instance begins with a line containing two integers, 1≤n≤100 and m. n is the number of tasks (numbered from 1 to n) and m is the number of direct precedence relations between tasks. After this, there will be m lines with two integers i and j, representing the fact that task i must be executed before task j.

An instance with n = m = 0 will finish the input.

Output

For each instance, print a line with n integers representing the tasks in a possible order of execution.

SampleInput

5 4
1 2
2 3
1 3
1 5
0 0

SampleOutput

1 4 2 5 3

假设有n个变量,还有m个二元组(u, v),分别表示变量u小于v。那么,所有变量从小到大排列起来应该是什么样子的呢?例如,有4个变量a, b, c, d,若已知a < b,c < b,d < c,则这4个变量的排序可能是a < d < c < b。尽管还有其他可能(如d < a < c < b),你只需找出其中一个即可。

第一种解法和第二种解法的原理都是一样的,采用了DFS,第二种解法使用了逆邻接表和vector容器,数据量大也不会有溢出问题,而且也提高了减少了使用空间,缺点就是第二种可能要比第一种难懂一些。

#include <iostream>
#include <cstring>

using namespace std;

const int maxNum = 105;
// n个节点,m条边
int n, m;
// 图
int G[maxNum][maxNum];
// 拓扑序列
int topo[maxNum];
// 在拓扑序列数组的位置
int t;
// 访问数组
// 0:未访问过 1:已访问过 -1:正在访问
int c[maxNum];

// 深度优先遍历c
bool dfs(int u) {
    // 置该节点正在访问
    c[u] = -1;
    for(int v = 0; v < n; v++) {
        if(G[u][v]) {
            // 存在有向环
            if(c[v] < 0) {
                return false;
            } else if(!c[v]) {
                dfs(v);
            }
        }
    }
    c[u] = 1;
    topo[--t] = u;
    return true;
}

// topo排序
bool topoSort() {
    t = n;
    memset(c, 0, sizeof(c));
    for(int u = 0; u < n; u++) {
        // 未访问过
        if(!c[u]) {
            // 存在有向环
            if(!dfs(u)) {
                return false;
            }
        }
    }
    return true;
}

int main() {
    while(cin >> n >> m) {
        if(n == 0) {
            break;
        }
        // 初始化图
        memset(G, 0 , sizeof(G));
        int a, b;
        for(int i = 0; i < m; i++) {
            cin >> a >> b;
            G[a - 1][b - 1] = 1;
        }

        if(topoSort()) {
            for(int i = 0; i < n - 1; i++) {
                cout << topo[i] + 1 << " ";
            }
            cout << topo[n - 1] + 1 << endl;
        }
    }
    return 0;
}
#include <iostream>
#include <vector>
#include <cstring>

using namespace std;

const int maxNum = 105;
int n, m;
// 图
// 逆邻接表
// 该节点存在且G[i].size() == 0 则证明无指向该节点的边
vector<int> G[maxNum];
vector<int> ans;

// 访问位
int visited[maxNum];

bool dfs(int u) {
    // 正在访问
    visited[u] = -1;
    for(int v = 0; v < G[u].size(); v++) {
        // 存在有向环
        if(visited[G[u][v]] < 0) {
            return false;
        } else if(visited[G[u][v]] == 0) {
            dfs(G[u][v]);
        }
    }
    // 访问过
    visited[u] = 1;
    ans.push_back(u);
    return true;
}

bool topoSort() {
    memset(visited, 0, sizeof(visited));
    for(int u = 0; u < n; u++) {
        // 访问未访问的节点
        if(visited[u] == 0) {
            if(!dfs(u)) {
                return false;
            }
        }
    }
    return true;
}


int main() {
    while(cin >> n >> m) {
        if(n == 0) {
            break;
        }
        int a, b;
        // 初始化
        ans.clear();
        for(int i = 0; i < maxNum; i++) {
            G[i].clear();
        }
        for(int i = 0; i < m; i++) {
            cin >> a >> b;
            // 逆邻接表
            G[b - 1].push_back(a - 1);
        }
        if(topoSort()) {
            for(int i = 0; i < ans.size() - 1; i++) {
                cout << ans[i] + 1 << " ";
            }
            cout << ans[ans.size() - 1] + 1 << endl;
        }
    }
    return 0;
}

你可能感兴趣的:(ACM,uva,UVa10305)