zoukankan      html  css  js  c++  java
  • 拓扑排序

    写在前面:我是一只蒟蒻

    好了,我们步入正题。

    首先,我们介绍一下AOV网的概念

    AOV网
    定义:在现代化管理中,人们常用有向图来描述和分析一项工程的计划和实施过程,一个工程常被分为多个小的子工程,这些子工程被称为活动(Activity),在有向图中若以顶点表示活动,有向边表示活动之间的先后关系,这样的图简称为AOV网。

    了解了AOV网后,我们就开始介绍我们的拓排。
    拓扑排序算法,是只适用于AOV网(DAG图“有向无环图”)
    把AOV网中的所有活动排成一个序列, 使得每个活动的所有前驱活动都排在该活动的前面,这个过程称为“拓扑排序”,所得到的活动序列称为“拓扑序列”。

    拓扑排序的过程大概是这样的:
    ① 选择一个入度为0 的结点并直接输出。
    ② 删除这个结点以及与它关联的所有边。
    ③ 重复步骤①和②,直到找不到入度为0 的结点。
    通常情况下,在实现的时候会维护一个队列以及每个结点的入度。
    在删除边的时候顺便把相应结点的入度减去,当这个结点入度为0 的时候直接将其加入队列。

    了解了主要的思想,我们来看一看主代码

     1 void topo(){
     2     int now;
     3     queue<int >q;//定义队列维护 
     4     for(int i=1;i<=n;i++){
     5         if(!in[i])q.push(i);//如果入度为零,则入队,in[]表示是否入队 
     6     }
     7     while(!q.empty()){
     8         now=q.front();q.pop();
     9         ans[++cnt]=now;
    10         for(int i=head[now];i;i=e[i].next){
    11             in[e[i].to]--;//与这个点有关的点的入度-- 
    12             if(!in[e[i].to])q.push(e[i].to);//如果入度为0,则入队 
    13         }
    14     }
    15     if(cnt!=n)printf("-1");//如果是环,则没有拓排序,则输出-1 
    16     else for(int i=1;i<=n;i++)printf("%d",ans[i]); //否则,输出拓排序 
    17 }

    如果还不是太明白

    我们来模拟一下

        第一开始,这是一张有向图

    我们将A点入队,将与A点有关的边删掉就得到了

      此时就成了这样子(好丑啊,有木有~~)我们来改一下  

         嗯这样好多了^_^

    此时,B与C的入度都为1,所以入队(谁先都无所谓)就先B入队

    自动跳过C入队

    得到

    再入队。

    结束。

    输出队列,就是我们要的拓排序~^_^~.

    下面,我们来看一道(栗)题

    Problem Description
    有N个比赛队(1<=N<=500),编号依次为1,2,3,。。。。,N进行比赛,比赛结束后,裁判委员会要将所有参赛队伍从前往后依次排名,但现在裁判委员会不能直接获得每个队的比赛成绩,只知道每场比赛的结果,即P1赢P2,用P1,P2表示,排名时P1在P2之前。现在请你编程序确定排名。
     
    Input
    输入有若干组,每组中的第一行为二个数N(1<=N<=500),M;其中N表示队伍的个数,M表示接着有M行的输入数据。接下来的M行数据中,每行也有两个整数P1,P2表示即P1队赢了P2队。

    Output
    给出一个符合要求的排名。输出时队伍号之间有空格,最后一名后面没有空格。

    其他说明:符合条件的排名可能不是唯一的,此时要求输出时编号小的队伍在前;输入数据保证是正确的,即输入数据确保一定能有一个符合要求的排名。
     
    Sample Input

    4 3 1 2 2 3 4 3
     
    Sample Output

    1 2 4 3

     思路分析:

    这个题的思路就是一道裸的拓排,因为按照题目要求,只有一场比赛打完才能知道他的排名,所以我们就非常Happy的用了拓排。

    嗯,代码的话,大家自食其力吧~~

  • 相关阅读:
    codevs 1766 装果子
    codevs 1415 比那名居天子
    codevs 1388 砍树
    codevs 1373 射命丸文
    codevs 2867 天平系统3
    codevs 2866 天平系统2
    codevs 2865 天平系统1
    codevs 2832 6个朋友
    广搜优化题目总结
    Codeforces Round #578 (Div. 2)
  • 原文地址:https://www.cnblogs.com/xishirujin/p/10410744.html
Copyright © 2011-2022 走看看