You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

77 lines
2.9 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include <bits/stdc++.h>
using namespace std;
/**
思路:非停靠-->停靠站连边,然后用拓扑排序求深度。
*/
const int N = 1010; //题目中要求结点数是1000个上限
int n, m; //n个车站,m个车次
vector<int> edge[N]; //邻接表
int in[N]; //入度数组
bool flag[N]; //flag[i]标识是不是停靠站点
bool st[N][N]; //用来判断是不是已经存在了i到j的边
int ans; //答案
int a[N]; //停靠站信息
//结构体,携带两个信息,一个是哪个车站,另一个是几级
struct Node {
int sq_sum;
int step;
};
//拓扑排序,计算出层次
void topSort() {
//拓扑排序
queue<Node> q; //拓扑用队列
//查找所有入度为0的结点入队列,第一个参数是结点号,第二个参数是步数
for (int i = 1; i <= n; ++i) if (!in[i]) q.push({i, 1});
//开始拓扑套路
while (!q.empty()) {
//结点ID
int u = q.front().num;
//步数
int step = q.front().step;
q.pop();
//注意修改ans的值保持最大值
ans = max(ans, step);
for (auto v:edge[u]) {
in[v]--;
if (!in[v]) q.push({v, step + 1});
}
}
}
int main() {
cin >> n >> m;
while (m--) {
//每次重新初始化状态数组
memset(flag, 0, sizeof(flag));
int s; //本轮的停靠站数量
cin >> s;
//读入停靠站信息
for (int i = 1; i <= s; ++i) cin >> a[i], flag[a[i]] = true; //标识是停靠站
//遍历出发站到终点站,这里可不是全部车站啊!只有在范围内的才能明确等级关系啊!!!注意
//这里a[1]是指起点a[s]是指终点,就是这个车次的出发点到结束点,这中间有停靠的,有不停靠的,
// 不停靠的站等级一定是小于停靠的
for (int i = a[1]; i <= a[s]; ++i)
//如果不是停靠站,那就是等级低的站,需要连边~,非停靠站-->停靠站 连边
if (!flag[i]) {
int source = i; //出发结点,在这里是指非停靠站点
for (int j = 1; j <= s; ++j) {
int target = a[j]; //a[j]代表所有依靠站
if (!st[source][target]) {//没配置过边的有效,重边只留一条.因为不同的车次,
// 存在两条一样的边是很正常的,但没有必要保留多个。
edge[source].push_back(target);
st[source][target] = true;//标识已配置
in[target]++;//入度++
}
}
}
}
//拓扑排序
topSort();
//输出结果
cout << ans << endl;
return 0;
}