数据结构实验之图论十:判断给定图是否存在合法拓扑序列

1、拓扑排序的介绍

对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若边(u,v)∈E(G),则u在线性序列中出现在v之前。
拓扑排序对应施工的流程图具有特别重要的作用,它可以决定哪些子工程必须要先执行,哪些子工程要在某些工程执行后才可以执行。为了形象地反映出整个工程中各个子工程(活动)之间的先后关系,可用一个有向图来表示,图中的顶点代表活动(子工程),图中的有向边代表活动的先后关系,即有向边的起点的活动是终点活动的前序活动,只有当起点活动完成之后,其终点活动才能进行。通常,我们把这种顶点表示活动、边表示活动间先后关系的有向图称做顶点活动网(Activity On Vertex network),简称AOV网。
一个AOV网应该是一个有向无环图,即不应该带有回路,因为若带有回路,则回路上的所有活动都无法进行(对于数据流来说就是死循环)。在AOV网中,若不存在回路,则所有活动可排列成一个线性序列,使得每个活动的所有前驱活动都排在该活动的前面,我们把此序列叫做拓扑序列(Topological order),由AOV网构造拓扑序列的过程叫做拓扑排序(Topological sort)。AOV网的拓扑序列不是唯一的,满足上述定义的任一线性序列都称作它的拓扑序列。

2、拓扑排序的实现步骤

  1. 在有向图中选一个没有前驱的顶点并且输出
  2. 从图中删除该顶点和所有以它为尾的弧(白话就是:删除所有和它有关的边)
  3. 重复上述两步,直至所有顶点输出,或者当前图中不存在无前驱的顶点为止,后者代表我们的有向图是有环的,因此,也可以通过拓扑排序来判断一个图是否有环。
关于代码,我有一点,就是第二层for循环里的break,一旦找到一个入度为0的点立刻跳出本次循环,因为,外围的for循环个数为n,第二层for循环如果多删一个(删除个数大于一)那么就会导致最后节点删完还在for循环。

下面是这个题

数据结构实验之图论十:判断给定图是否存在合法拓扑序列

Time Limit: 1000 ms Memory Limit: 65536 KiB

Problem Description

 给定一个有向图,判断该有向图是否存在一个合法的拓扑序列。

Input

 输入包含多组,每组格式如下。

第一行包含两个整数n,m,分别代表该有向图的顶点数和边数。(n<=10)

后面m行每行两个整数a b,表示从a到b有一条有向边。

Output

 若给定有向图存在合法拓扑序列,则输出YES;否则输出NO。

Sample Input

1 0
2 2
1 2
2 1

Sample Output

YES
NO
#include <iostream>
#include <bits/stdc++.h>
using namespace std;

int main()
{
    int n,m,i,j,k,flag,a,b;
    while(scanf("%d %d",&n,&m)!=EOF)
    {
        int mapp[12][12]={{0,0}};
        int du[12]={0};
        int vis[12]={0};
        for(i=1;i<=m;i++)
        {
            scanf("%d %d",&a,&b);
            mapp[a][b]=1;
            du[b]++;
        }
        for(i=1;i<=n;i++)
        {
            flag=0;
            for(j=1;j<=n;j++)
            {
                if(vis[j]==0&&du[j]==0)
                {
                    flag=1;
                    for(k=1;k<=n;k++)
                    {
                        if(mapp[j][k])
                            du[k]--;
                    }
                    vis[j]=1;
                    break;
                }
            }
            if(flag==0)
            {
                break;
            }
        }
        if(flag)
        {
            printf("YES\n");
        }
        else
        {
            printf("NO\n");
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/w13884794538/article/details/79995917