![0df1aa2e94a9742f83cefccf854cf56a.png](https://i-blog.csdnimg.cn/blog_migrate/73055d94e1b5f33569ebcc8bc666ee0e.jpeg)
拓扑排序是对DAG(有向无环图)上的节点进行排序,使得对于每一条有向边
![equation?tex=u%5Crightarrow+v](https://i-blog.csdnimg.cn/blog_migrate/5f1e91bab93b8acd966e42a34ad7ca31.png)
![equation?tex=u](https://i-blog.csdnimg.cn/blog_migrate/ad57b04afaa64e4c3414210504fe8806.png)
![equation?tex=v](https://i-blog.csdnimg.cn/blog_migrate/2bd40b4a76c2cad53a0283bfbae48e61.png)
拓扑排序最经典的算法是Kahn算法。首先,先拿出所有入度为0的点排在前面,并在原图中将它们删除:
![8ec9479a9e4560ed71bd7b36c144dcc7.png](https://i-blog.csdnimg.cn/blog_migrate/6f43a0e67e490481d4568adbc74379ca.jpeg)
这时有些点的入度减少了,于是再拿出当前所有入度为0的点放在已经排序的序列后面,然后删除:
![7399ab9331797959ab8f36095c938184.png](https://i-blog.csdnimg.cn/blog_migrate/ecf6075ab133e75334cd951d804e543d.jpeg)
因为是有向无环图,而且删除操作不会产生环,所以每时每刻都一定存在入度为0的点,一定可以不断进行下去,直到所有点被删除。
![a84a31c619dc9c5f89d9fe30a1cb4ea7.png](https://i-blog.csdnimg.cn/blog_migrate/3b35383dbc4db67ea3cfbe95a2ac3f8f.jpeg)
以下是一个
![equation?tex=O%28n%2Bm%29](https://i-blog.csdnimg.cn/blog_migrate/6a7dcb3136b786ed7d7fafb3aab0bb0d.png)
![equation?tex=n%2Cm](https://i-blog.csdnimg.cn/blog_migrate/b1f1ce215b73081505dbea9a886f8486.png)
// 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](https://i-blog.csdnimg.cn/blog_migrate/324e07a19afe437b37f888cf8d7e4190.png)
这里有一道例题:
(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 compareand
, first we find the leftmost position with differing characters:
. If there is no such position (i. e.
is a prefix of
or vice versa) the shortest string is less. Otherwise, we compare characters
and
Inputaccording to their order in alphabet.
The first line contains an integer(
): number of names.
Each of the following n lines contain one string(
), the
Output-th name. Each name contains only lowercase Latin letters. All names are different.
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](https://i-blog.csdnimg.cn/blog_migrate/ce59f55893efd960f1dbdfcd5c192a96.png-1)
![equation?tex=r%3Cs](https://i-blog.csdnimg.cn/blog_migrate/e927b5925c8e7615b04dcced77863774.png)
![equation?tex=s%3Ca](https://i-blog.csdnimg.cn/blog_migrate/4aa2212c7a3ae4ce1b94a8e3bcb39211.png%3Ca)
Pecco:算法学习笔记(目录)zhuanlan.zhihu.com