1. 理解拓扑排序
首先,我们知道拓扑排序可以处理一些现实生活中有次序的事件,所以本质上还是一种排序,但是在实际应用场景中,我们需要建模一种“大小”顺序。
比如说, 洛谷P1983这道题,其实理解其本质就是等级小的点才可以通向等级高的点,等级高低就是这道题排序的标准
代码:
#include <bits/stdc++.h>
using namespace std;
int n, m;
int edge[1001][1001]; // 存储依赖关系的邻接矩阵
vector<int> mp[1001]; // 邻接表
int in[1001]; // 入度数组
bool vis[1001]; // 访问标记
int s[1001]; // 存储每一趟车次的停靠站
struct node {
int level; // 当前车站的级别
int id; // 当前车站的编号
};
queue<node> q;
int main() {
cin >> n >> m;
// 处理每一趟车次
for (int i = 1; i <= m; i++) {
int x;
cin >> x;
fill(vis + 1, vis + n + 1, 0); // 初始化vis数组
// 读取停靠站信息
for (int i = 1; i <= x; i++) {
cin >> s[i];
vis[s[i]] = 1; // 标记该站点已被访问
}
// 建立依赖关系
for (int i = s[1]; i <= s[x]; i++) {
if (!vis[i]) {
for (int j = 1; j <= x; j++) {
if (!edge[i][s[j]]) {
mp[i].push_back(s[j]);
edge[i][s[j]] = 1; // 表示 i 到 s[j] 有依赖关系
in[s[j]]++; // s[j] 的入度增加
}
}
}
}
}
// 初始化队列,将所有入度为 0 的节点加入队列
for (int i = 1; i <= n; i++) {
if (!in[i]) q.push({1, i});
}
int maxLevel = 0; // 记录最大级别
// 执行 BFS
while (!q.empty()) {
node now = q.front();
q.pop();
// 更新与当前车站相关的所有站点的级别
for (int i = 0; i < mp[now.id].size(); i++) {
in[mp[now.id][i]]--;
if (!in[mp[now.id][i]]) {
q.push({now.level + 1, mp[now.id][i]});
maxLevel = max(maxLevel, now.level + 1);
}
}
}
// 输出最少级别数
cout << maxLevel << endl;
return 0;
}