拓扑排序

发布时间 2023-08-07 19:31:27作者: DLSQS

拓扑序列是顶点活动网中将活动按照发生的先后顺序进行的一种排列。

 

拓扑排序,是对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若边(u,v)∈E(G),则u在线性序列中出现在v之前。通常,这样的线性序列称为满足拓扑次序(Topological Order)的序列,简称拓扑序列。

 

有向无环图一定存在拓扑序列,所以有向无环图又被称为拓扑图。

以洛谷p4017最大食物链计数为例

主要代码如下:

 1 const int N = 5e5 + 10, inf = 0x3f3f3f3f3f3f3f3f, mod = 80112002;
 2 vector<int> vt[N];
 3 queue<int> q;
 4 bool book1[N], book2[N];
 5 int n, m, in[N], out[N], num[N];
 6 void solve() {
 7     cin >> n >> m;
 8     for (int i = 1; i <= m; i++) {
 9         int x, y;
10         cin >> x >> y;
11         vt[x].push_back(y);//记录x的出边
12         in[y]++;//y的入边条数+1
13         out[x]++;//x的入边条数+1
14     }
15     for (int i = 1; i <= m; i++)
16         if (!in[i]) {//找到没有入边的点作为起点
17             q.push(i);//将其入队
18             num[i] = 1;
19         }
20     while (!q.empty()) {
21         int to = q.front();
22         q.pop();
23         for (auto it : vt[to]) {//遍历队首元素的出边到达的点
24             in[it]--;//将其入边-1
25             num[it] = (num[it] + num[to]) % mod;//路径数量为入边+出边的条数
26             if (!in[it])q.push(it);//没有入边的话将点入队
27         }
28     }
29     int ans = 0;
30     for (int i = 1; i <= n; i++)
31         if (!out[i])//找到没有出边的点,其为最终点
32             ans = (ans + num[i]) % mod;
33     cout << ans;
34 }