题目:https://vjudge.net/problem/UVA-10305

基础知识:


拓扑排序:把一个图中的所有结点排序,对于每一条有向边(u,v),使u都在v的前面

如图中存在有向环,则不存在拓扑排序,反之存在。

不包含有向环的有向图称为有向无环图DAG(Directed Acyclic Graph)

 

解题思路:


本题是一道拓扑排序模版题,注意,在用dfs完成拓扑排序时,在访问完一个结点后要把它加到当前拓扑排序数组的尾部

c[u]=0;表示从未访问过(未调用dfs(u))

c[u]=1;表示已经访问过,并且递归访问过它的所有子孙(dfs(u)已返回结果)

c[u]=-1;表示正在访问,(dfs(u)正在栈帧中,但未返回)

 

ac代码:


#include <iostream>
#include <cmath>
#include <cstring>
#include <cctype>
#include <algorithm>
#include <stdlib.h>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <sstream>
#define maxn 110
#define inf 1e+9+10
using namespace std;
typedef long long ll;
int n,m,t,c[maxn],topo[maxn],G[maxn][maxn];
bool dfs(int u)
{
    c[u]=-1;//正在访问
    for(int v=1;v<=n;v++)
        if(G[u][v])
        {
            if(c[v]<0)//存在有向环
                return false;
            else if(!c[v]&&!dfs(v)) return false;//v未访问且以其继续bfs会false
        }
    c[u]=1;//已访问完毕
    topo[--t]=u;
    return true;
}
bool toposort()
{
    t=n;
    memset(c,0,sizeof(c));
    for(int u=1;u<=n;u++)
        if(!c[u])//未访问过
            if(!dfs(u)) return false;//拓扑排序失败
    return true;
}
int main()
{
    //freopen("/Users/zhangkanqi/Desktop/11.txt","r",stdin);
    //ios::sync_with_stdio(false);
    int a,b,i;
    while(scanf("%d %d",&n,&m)==2)
    {
        if(m==0&&n==0) break;
        memset(G,0, sizeof(G));
        for(i=0;i<m;i++)
        {
            scanf("%d %d",&a,&b);
            G[a][b]=1;
        }
        toposort();
        for(i=0;i<n;i++)
        {
            if(i)
                printf(" ");
            printf("%d",topo[i]);
        }
        printf("\n");
    }
    return 0;
}