车站分级
题目描述
一条单向的铁路线上,依次有编号为 \(1, 2, ..., n\)的 \(n\)个火车站。每个火车站都有一个级别,最低为 \(1\) 级。现有若干趟车次在这条线路上行驶,每一趟都满足如下要求:如果这趟车次停靠了火车站 \(x\),则始发站、终点站之间所有级别大于等于火车站\(x\) 的都必须停靠。(注意:起始站和终点站自然也算作事先已知需要停靠的站点)
例如,下表是\(5\)趟车次的运行情况。其中,前\(4\) 趟车次均满足要求,而第 \(5\) 趟车次由于停靠了 \(3\) 号火车站(\(2\) 级)却未停靠途经的 \(6\) 号火车站(亦为 \(2\) 级)而不满足要求。
现有 \(m\) 趟车次的运行情况(全部满足要求),试推算这$ n$ 个火车站至少分为几个不同的级别。
输入输出格式
输入格式
第一行包含 \(2\) 个正整数 \(n, m\),用一个空格隔开。
第 \(i + 1\) 行\((1 ≤ i ≤ m)\)中,首先是一个正整数 \(s_i(2 ≤ s_i ≤ n)\),表示第$ i$ 趟车次有 \(s_i\) 个停靠站;接下来有$ s_i$个正整数,表示所有停靠站的编号,从小到大排列。每两个数之间用一个空格隔开。输入保证所有的车次都满足要求。
输出格式
一个正整数,即 \(n\) 个火车站最少划分的级别数。
输入输出样例
输入样例 #1
9 2
4 1 3 5 6
3 3 5 6
输出样例 #1
2
输入样例 #2
9 3
4 1 3 5 6
3 3 5 6
3 1 5 9
输出样例 #2
3
说明
对于\(20\%\)的数据,\(1 ≤ n, m ≤ 10\);
对于 \(50\%\)的数据,\(1 ≤ n, m ≤ 100\);
对于 \(100\%\)的数据,\(1 ≤ n, m ≤ 1000\)。
分析
此题我们要抓住原题中的一句话:
如果这趟车次停靠了火车站 \(x\),则始发站、终点站之间所有级别大于等于火车站\(x\) 的都必须停靠。
反过来也就是说:
在一个车次中,停下来的车站一定比没停下来的车站的级别高。
现在让你求最少分为多少级,也就是说,我们用 \(1, 2, 3, 4\) 给级别编号,程序让我们求的就是最高的那个级别。
既然在一个车次中停下来的车站一定比没停下来的车站的级别高,我们就可以根据这个让级别低的向级别高的连边,最终就会形成一个DAG。对于这个DAG进行topsort,并同时进行递推,便可以得出每一个车站的等级了,最后取等级最大值即可。
上代码。
代码
/*
* @Author: crab-in-the-northeast
* @Date: 2020-10-01 09:14:56
* @Last Modified by: crab-in-the-northeast
* @Last Modified time: 2020-10-01 11:32:31
*/
#include
#include
#include
#include
const int maxn = 1005;
const int maxm = 1005;
std :: vector G[maxn];
int ind[maxn];
bool vis[maxn][maxn];
int n, m;
int topsort() {
std :: queue > q;
int ans = 1;
for (int i = 1; i <= n; ++i)
if (ind[i] == 0)
q.push(std :: make_pair(i, 1));
while (!q.empty()) {
int u = q.front().first, level = q.front().second;
q.pop();
for (int i = 0; i < G[u].size(); ++i) {
int v = G[u][i];
--ind[v];
if (ind[v] == 0) {
q.push(std :: make_pair(v, level + 1));
ans = ans > level + 1 ? ans : level + 1;
}
}
}
return ans;
}
int main() {
std :: scanf("%d %d", &n, &m);
for (int i = 1; i <= m; ++i) {
int s;
std :: scanf("%d", &s);
int stop[maxn];
bool is_stop[maxn] = {false};
for (int j = 1; j <= s; ++j) {
std :: scanf("%d", &stop[j]);
is_stop[stop[j]] = true;
}
for (int j = stop[1]; j <= stop[s]; ++j) {
if (!is_stop[j]) {
for (int k = 1; k <= s; ++k) {
if (!vis[j][stop[k]]) {
++ind[stop[k]];
G[j].push_back(stop[k]);
vis[j][stop[k]] = true;
}
}
}
}
}
std :: printf("%d\n", topsort());
return 0;
}
评测记录