拓扑排序

写在前面:我是一只蒟蒻

好了,我们步入正题。

首先,我们介绍一下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的用了拓排。

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

 

posted @ 2019-02-21 10:16  惜时如金  阅读(225)  评论(0编辑  收藏  举报