zoukankan      html  css  js  c++  java
  • [旧版][知识点]拓扑排序

    // 此博文为迁移而来,写于2015年2月24日,不代表本人现在的观点与看法。原始地址:http://blog.sina.com.cn/s/blog_6022c4720102vspe.html

     

    Update - 20200607

    该博文内容现已更新并迁移至:

    [知识点] 8.4 拓扑排序与关键路径 https://www.cnblogs.com/jinkun113/p/13057781.html

    1、前言
    在了解拓扑排序之前,我们先来看一道题目以更好的理解:
     
           一个较大的工程往往被划分成许多子工程,我们把这些子工程称作活动(activity)。在整个工程中,有些子工程(活动)必须在其它有关子工程完成之后才能开始,也就是说,一个子工程的开始是以它的所有前序子工程的结束为先决条件的,但有些子工程没有先决条件,可以安排在任何时间开始。为了形象地反映出整个工程中各个子工程(活动)之间的先后关系,可用一个有向图来表示,图中的顶点代表活动(子工程),图中的有向边代表活动的先后关系,即有向边的起点的活动是终点活动的前序活动,只有当起点活动完成之后,其终点活动才能进行。通常,我们把这种顶点表示活动、边表示活动间先后关系的有向图称做顶点活动网(Activity On Vertex network),简称AOV网。
     
             课程代号      课程名称        先修课程
               C1          高等数学             无
               C2          程序设计基础      无
               C3          离散数学             C1,C2
               C4          数据结构             C3,C5
               C5          算法语言             C2
               C6          编译技术             C4,C5
               C7          操作系统             C4,C9
               C8          普通物理             C1
               C9          计算机原理         C8
     
    其AOV网如图所示:
     


    2、什么是拓扑排序?
           一个AOV网应该是一个有向无环图,即不应该带有回路,因为若带有回路,则回路上的所有活动都无法进行。一个具有三个顶点的回路,由边可得B活动必须在A活动之后,由边可得C活动必须在B活动之后,所以推出C活动必然在A活动之后,但由边可得C活动必须在A活动之前,从而出现矛盾,使每一项活动都无法进行。这种情况若在程序中出现,则称为死锁或死循环,是应该必须避免的。
           在AOV网中,若不存在回路,则所有活动可排列成一个线性序列,使得每个活动的所有前驱活动都排在该活动的前面,我们把此序列叫做拓扑序列(Topological order),由AOV网构造拓扑序列的过程叫做拓扑排序(Topological sort)。AOV网的拓扑序列不是唯一的,满足上述定义的任一线性序列都称作它的拓扑序列。例如,下面的三个序列都是上图的拓扑序列,当然还可以写出许多。
        (1) C1,C8,C9,C2,C3,C5,C4,C7,C6
        (2) C2,C1,C3,C5,C4,C6,C8,C9,C7
        (3) C1,C2,C3,C8,C9,C5,C4,C6,C7
     
    3、有什么作用?
           除了上面我们之前我们展示的一道题目,拓扑排序的应用是比较广泛的。下面我们再看一个例子:
     
    士兵排队 Soldier.cpp
    <1>问题描述
           有N名士兵(1<=N<=26),编号依次为A,B,C,……进行队列训练时,指挥官要把一些士兵从高到矮依次排成一行,但现在指挥官不能直接获得每个士兵的身高信息,只能获得“P1比P2高”这样的比较结果(P1,P2∈{A,B,…Z},记为P1>P2),如“A>B”表示A比B高。编一程序,根据所得到的比较结果求出符合条件的排队方案。注:比较结果中没有涉及到的士兵不参加排队。
           例如,设有3个士兵,A、B、C,给出关系(A,B),(B,C)。其中(A,B)表示士兵A高于B,当上面的关系给出之后,可以将他们排成一队:ABC。
     
    <2>输入
           通过文件输入,每个比较结果在文件中占一行。
    <3>输出
           若输入数据无解或不能唯一确定,则输出“NO  ANSWER!”,否则从高到矮依次输出每一个士兵的编号,中间无分隔符,并把结果写入文本文件中。
     
    <4>输入样例
    A>B
    B>F
    F>D
    <5>输出样例
    ABFD
     
    代码如下:
     
    #include<cstdio>
    #include<cstdlib>
    #define MAXN 28
     
    struct edge
    {
      int next,v;
    };
    edge list[MAXN*2];
    int head[MAXN],tot,n,have[MAXN],ListNum[MAXN],del[MAXN],get,ans[MAXN];
     
    void AddList(char strU,char strV)
    {
      int u=strU-64,v=strV-64;
      have[u]=have[v]=1;
      tot++;
      list[tot].v=v;
      list[tot].next=head[u];
      head[u]=tot;
      ListNum[v]++;
    }
     
    void init()
    {
      char s[4];
      freopen("3.in","r",stdin);
      freopen("3.out","w",stdout);
      while (scanf("%s",s)!=EOF) AddList(s[0],s[2]);
      for (int i=1;i<=26;i++)
        if (have[i]==1) n++;
    }
     
    int check()
    {
      for (int i=1;i<=26;i++)
        if (del[i]!=1 && have[i]==1) return 0;
      return 1;
    }
     
    void DFS(int now,int dep)
    {
      del[now]=1;
      for (int x=head[now];x!=0;x=list[x].next)
        ListNum[list[x].v]--;
      ans[dep]=now;
      if (check()==1) 
      {
        if (get==1) { printf("NO ANSWER!"); exit(0); }
        else { get=1; return; }
      }
      for (int i=1;i<=26;i++)
        if (ListNum[i]==0 && del[i]!=1 && have[i]==1) DFS(i,dep+1);
      for (int x=head[now];x!=0;x=list[x].next)
        ListNum[list[x].v]++;
      del[now]=0;
    }
     
     
    int main()
    {
      init();
      for (int i=1;i<=26;i++) 
        if (ListNum[i]==0 && have[i]==1) DFS(i,1);
      if (get==0) printf("NO ANSWER!");
      else for (int i=1;i<=n;i++) printf("%c",ans[i]+64);
      return 0;
    }

     

  • 相关阅读:
    Splunk Fundamentals 2 – Lab Exercises
    Splunk Fundamentals 1 Lab Exercises
    python交换机自动化巡检
    nginx web服务器
    linux tips
    web服务器统计情况
    HTTP请求报文和响应报文
    python 之路 day 14 HTML CSS
    python 之路 13 ORM SQLAlchemy
    python 之路12 RabbitMQ Python 操作mysql
  • 原文地址:https://www.cnblogs.com/jinkun113/p/4677200.html
Copyright © 2011-2022 走看看