uva10305(拓扑排序dfs)

来源:互联网 发布:医学统计学软件 编辑:程序博客网 时间:2024/05/18 13:46

https://vjudge.net/problem/UVA-10305(uva0305 点击打开链接)

思路:有向无环图才有拓扑排序。判断是有向无环图后,找入度为0的点,然后把这个点以及从该点到其他点的边去掉,重复寻找入度为0 的点存下来,存下来的点就是拓扑排序后的序列。

分析:可以用队列写,也可以用dfs写。队列复杂度高,易理解;dfs复杂度低,难理解(算法竞赛入门经典上用dfs写的,就照着dfs写的)。

代码:

#include <iostream>#include <algorithm>#include <cstring>#include <string>#include <cstdio>using namespace std;const int maxn = 100 + 10;int g[maxn][maxn];//点与点之间的边int c[maxn];//记录是否被访问过,0 表示为访问过,-1 表示正在访问  1 表示已经访问过了int topo[maxn];//存入度为0的点,就拓扑序列int n,m,t;bool dfs(int u){    c[u] = -1;    for(int i = 0;i < n;i++)    {        if(g[u][i])//如果u到i有边        {            if(c[i] < 0)//如果i点正在被访问,说明i和u是同一个点,是自环,无拓扑排序                return false;            if(!c[i] && !dfs(i))//如果i未被访问过,但是dfs不满足                return false;        }    }    c[u] = 1;//标记已被访问过    topo[--t] = u;//u是拓扑排序后的最后一个点    return true;}bool toposort(){    t = n;    memset(c,0,sizeof(c));    for(int i = 0;i < n;i++)    {        if(!c[i])//如果i点没有访问过        {            if(!dfs(i))//就访问i点            {                return false;            }        }    }    return true;}int main(){    while(scanf("%d%d",&n,&m),n)    {        memset(g,0,sizeof(g));        for(int i = 1;i <= m;i++)        {            int u,v;            scanf("%d%d",&u,&v);            g[--u][--v] = 1;//先--,因为点是从0开始存的        }        toposort();        for(int i = 0;i < n;i++)        {            if(i != 0)                printf(" ");            printf("%d",topo[i] + 1);//点是从0开始存的,但是实际是从1开始        }        printf("\n");    }}
原创粉丝点击