输出dag的所有拓扑排序序列_算法学习笔记(53): 拓扑排序

0df1aa2e94a9742f83cefccf854cf56a.png

拓扑排序是对DAG(有向无环图)上的节点进行排序,使得对于每一条有向边

equation?tex=u%5Crightarrow+v
equation?tex=u 都在
equation?tex=v 之前出现。简单地说,是在不破坏节点
先后顺序的前提下,把 DAG拉成一条 。如果以游戏中的科技树 (虽然名字带树,其实常常不是树而只是DAG)举例,拓扑排序就是找到一种 可能的点科技树的 顺序

拓扑排序最经典的算法是Kahn算法。首先,先拿出所有入度为0的点排在前面,并在原图中将它们删除:

8ec9479a9e4560ed71bd7b36c144dcc7.png

这时有些点的入度减少了,于是再拿出当前所有入度为0的点放在已经排序的序列后面,然后删除:

7399ab9331797959ab8f36095c938184.png

因为是有向无环图,而且删除操作不会产生环,所以每时每刻都一定存在入度为0的点,一定可以不断进行下去,直到所有点被删除。

a84a31c619dc9c5f89d9fe30a1cb4ea7.png

以下是一个

equation?tex=O%28n%2Bm%29 的实现(
equation?tex=n%2Cm 分别表示点数和边数),利用了队列:
// deg是入度,在存图的时候需要录入数据
// A是排序后的数组
int deg[MAXN], A[MAXN];
bool toposort(int n)
{
    int cnt = 0;
    queue<int> q;
    for (int i = 1; i <= n; ++i)
        if (deg[i] == 0)
            q.push(i);
    while (!q.empty())
    {
        int t = q.front();
        q.pop();
        A[cnt++] = t;
        for (auto to : edges[t])
        {
            deg[to]--;
            if (deg[to] == 0) // 出现了新的入度为0的点
                q.push(to);
        }
    }
    return cnt == n;
}

返回值为是否成功进行拓扑排序,也即是否存在环。也就是说拓扑排序是可以用来简单地判环的。有时会要求输出字典序最小的方案,这时把queue改成priority_queue即可,复杂度会多一个

equation?tex=%5Clog

这里有一道例题:

CF510C Fox And Names

Fox Ciel is going to publish a paper on FOCS (Foxes Operated Computer Systems, pronounce: "Fox"). She heard a rumor: the authors list on the paper is always sorted in the lexicographical order.
After checking some examples, she found out that sometimes it wasn't true. On some papers authors' names weren't sorted in lexicographical order in normal sense. But it was always true that after some modification of the order of letters in alphabet, the order of authors becomes lexicographical!
She wants to know, if there exists an order of letters in Latin alphabet such that the names on the paper she is submitting are following in the lexicographical order. If so, you should find out any such order. Lexicographical order is defined in following way. When we compare
equation?tex=s and
equation?tex=t , first we find the leftmost position with differing characters:
equation?tex=s_i+%5Cne+t_i . If there is no such position (i. e.
equation?tex=s is a prefix of
equation?tex=t or vice versa) the shortest string is less. Otherwise, we compare characters
equation?tex=s_i and
equation?tex=t_i according to their order in alphabet.
Input
The first line contains an integer
equation?tex=n (
equation?tex=1%E2%80%89%E2%89%A4%E2%80%89n%E2%80%89%E2%89%A4%E2%80%89100 ): number of names.

Each of the following n lines contain one string
equation?tex=name_i (
equation?tex=1%E2%80%89%E2%89%A4%E2%80%89%7Cname_i%7C%E2%80%89%E2%89%A4%E2%80%89100 ), the
equation?tex=i-th name. Each name contains only lowercase Latin letters. All names are different.
Output
If there exists such order of letters that the given names are sorted lexicographically, output any such order as a permutation of characters 'a'–'z' (i. e. first output the first letter of the modified alphabet, then the second, and so on).
Otherwise output a single word "Impossible" (without quotes). Examples input
3
rivest
shamir
adleman output
bcdefghijklmnopqrsatuvwxyz

简单地说,就是给出一张名字的列表,要找到一张字母表使得这张人名的列表是按字典序排列的。

通过对相邻的两个名字间进行比较,可以得到

equation?tex=n-1 个关系(如样例中
equation?tex=r%3Cs
equation?tex=s%3Ca ),它们可以构成一张图,而最后线性的字母表也必须要满足这些关系。很明显,如果这张图存在环,必然是无解的;而如果无环,那么拓扑排序即可得到结果。

Pecco:算法学习笔记(目录)​zhuanlan.zhihu.com
zhihu-card-default.svg
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值