图论之拓扑排序

拓扑排序是根据先后顺序排序,而不是根据大小来排序。
在有向无环图中,点与点之间有单向边相连,这表明一种约束关系。
例如A到B有一条边,那么A到B就有约束关系。
拓扑排序就是基于多个点之间的约束关系,生成一条线性序列。
首先要明白两个概念:
入度:进入某一点的边数。
出度:从某一点出发的边数。
A到B,B的入度加一,A的出度加一。
先来看一道例题:
有N个士兵(1<=N<=100),编号依次为1,2,…,N.队列训练时,指挥官要把士兵从高到矮排成一行,但指挥官只知道“1 比2 高,7 比 5高”这样的比较结果。
请编写一个程序,对于给出指挥官一些“a比b高”这样信息后,求出一种合理士兵从高到低的排列

在这道题目中,约束关系就是身高,我们可以把每个士兵理解为图中的一个点,A比B高,表明A对B有约束关系,我们就建立一条A到B的边来记录这种约束关系。
最终我们得到一个有向无环图。
这里写图片描述

懒得画图了,这是我网上随便找的图片。
假设现在有A,B,C,D,E五个士兵,我们已经根据约束关系建立了如图的图,然后我们开始进行拓扑排序。
首先找到收到约束最少的那个点(入度最小的点),从图中看,A点不受任何约束,所以A首先进队(要用到队列的知识,其实也可以理解为把A点放进最终序列里)。然后A点对其他点的约束就没了,所以B,D入度–。B点的入度成为了零,不受任何约束,B点进队。B点对其他点的约束没了,C点的入度–,C点的入度为零,进队。C点对D,E的约束没了,D,E入度–,D点入度为零,进队,对E点的约束没了,最后一个E点也进队。
至此,队列中已经形成了完整的拓扑序列。
拓扑排序的工作流程还是比较简单。
模版:

head=0,tail=0 //初始化队列;
for(int i=1;i<=n;i++)
{
    if(rd[i]==0)  
    que[tail++]=i;//先让队列中入度为0的点进队。 
} 
while(head<tail)
{
    head++;
    for(int i=1;i<=n;i++)
    {
        if(a[que[head]][i]==1)//与队列中得点相连的点的入度--; 
        {
            rd[i]--;
            if(rd[i]==0)     //如果减少到0,该点进队。 
            que[tail++]=i;
        }
    }
} 

其实拓扑排序主要是一种辅助工具,用来表示点与点的约束关系。

例题拓展
FireDancer来到一个神秘岛,他要从岛的西头到东头然后在东头的码头离开。可是当他走了一次后,发现这个岛的景色非常的美丽,于是他从东头的传送门传到了西头,换了一种走法又走了一遍。发现还不过瘾,又走了一遍……终于,FireDancer把所有的从西头到东头的路径都走了一遍。他站在岛东头的海滩上,突然想到了一个问题,那就是他一共花了多少时间。他把这个问题交给了你。

FireDancer把这个岛抽象成了一个图,共n个点代表路的相交处,m条边表示路,边是有向的(只能按照边的方向行走),且可能有连接相同两点的边。输入保证这个图没有环,而且从西头到东头至少存在一条路径。两条路径被认为是不同的当且仅当它们所经过的路不完全相同。

这道题的关键是求出起点到终点的方法数,这里需要用到一点组合数学的知识(其实也不用)
假如B到A有一条边,C到A也有一条边。那么从起点到A的方法数就是从起点到B的方法数加上从起点到C的方法数(好好想想)。
因为需要一种累加,所以我们可用拓扑排序,在求出序列的同时累加方法数。
然后这道题还要求出总时间,其实就是算出他所有方法经过的边的权值的总和。
假如有A到B有一条边,起点到A的方法数是Ta,那么显然起点经过A再到B的方法数也是Ta。这说明A,B之间这条边要被走Ta次,Ta*Vab就是这条边走过的总路径。
这里写图片描述
我美丽的图。
1到1方法数是1,1到2方法数是1,2到3是2,1到3是3.
1到2的总路径是1*5=5。
2到3的总路径是5+7+5+10=27
1到3直接的边是15
所以1到3所有路径之和是42。
这道题比较难理解,而且也很复杂。
我感觉我讲的不好,你们还是自己体会吧。。。
OJBK!!!

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值