Ordering Tasks UVA - 10305

本文深入探讨了拓扑排序算法的实现,通过两种不同的代码示例详细解释了使用队列和深度优先搜索(DFS)进行拓扑排序的过程。文章首先介绍了输入格式,包括任务数、依赖关系数量以及依赖关系的具体描述。随后,提供了两种实现方式,一种利用队列存储入度为0的任务节点,另一种则是基于深度优先搜索的经典实现。最后,通过样例输入和输出展示了算法的正确性和效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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 nish the input.

Output

For each instance, print a line with

n

integers representing the tasks in a possible order of execution.

Sample Input

5 4

1 2

2 3

1 3

1 5

0 0

Sample Output

1 4 2 5 3

 

题意:用拓扑排序找到一个拓扑序列并输出。

拓扑排序的实现有四个步骤:

1.用一个容器(我用的队列)存储入度为0的点。

2.删去容器中的点相关的所有边。

3.重复1,2直到DAG图为空 或者 找不到符合要求的点。

4.如果此时图不为空,则没有拓扑序列。

这里贴两份代码,一份用队列实现,没用dfs就AC了,另一份是紫书上刘汝佳的dfs实现拓扑排序的代码。

我的:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <string>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
using namespace std;
const int maxn = 10005;
int g[maxn][maxn];//点的邻接图
int u,v,n,m;//u,v是横纵坐标,n,m是题目上的n和m
int p[maxn];//p[i](1<=i<=n) 存放的是点i的入度
queue<int> s;//存放拓扑序列
int d[maxn];//做为标记数组,标记该点已经存入过队列s了
int main()
{
    while(cin>>n>>m && (n||m)){
        memset(g,0,sizeof(g));
        memset(p,0,sizeof(p));
        memset(d,0,sizeof(d));
        for(int i = 1;i <= m;i++){
            cin>>u>>v;
            g[u][v] = 1;
            p[v]++;
        }
        int t = 0;
        for(int i = 1;i <= n;i++){
            if(p[i] == 0){
                s.push(i);
                d[i] = 1;
            }
        }
        bool flag = true;//为了输出格式符合要求而设的变量
        if(s.empty()){cout<<"No"<<endl;continue;}
        else{
            cout<<s.front();
            flag = false;
        }
        while(!s.empty()){
            int a = s.front();
            if(flag)
                cout<<" "<<a;
            flag = true;
            s.pop();
            for(int i = 1;i <= n;i++){
                if(g[a][i] == 1) p[i]--;
                if(p[i] == 0 && !d[i]){
                    s.push(i);
                    d[i] = 1;
                }
            }
        }
        cout<<endl;

    }
    return 0;
}

 

刘老师的:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <string>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
using namespace std;
const int maxn = 10005;
int g[maxn][maxn];
int u,v,t,n,m;
int c[maxn];
int topo[maxn];
bool dfs(int u){
    c[u] = -1;
    for(int i = 1;i <= n;i++){
        if(g[u][i]){
            if(c[i] < 0) return false;
            else if(!c[i] && !dfs(i)) return false;
        }
    }
    c[u] = 1;topo[t--] = u;
    return true;
}

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


int main()
{
    while(cin>>n>>m && (n||m)){
        memset(g,0,sizeof(g));
        for(int i = 1;i <= m;i++){
            cin>>u>>v;
            g[u][v] = 1;
        }
        if(toposort()){
            for(int i = 1;i <= n-1;i++){
                cout<<topo[i]<<" ";
            }
            cout<<topo[n]<<endl;
        }
        else
            cout<<"No"<<endl;
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值