题解:洛谷 P1983 [NOIP 2013 普及组] 车站分级
【题目来源】
洛谷:[P1983 NOIP 2013 普及组] 车站分级 - 洛谷
【题目描述】
一条单向的铁路线上,依次有编号为 \(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\) 个火车站最少划分的级别数。
【输入样例】
9 2
4 1 3 5 6
3 3 5 6
【输出样例】
2
【算法标签】
《洛谷 P1983 车站分级》 #拓扑排序# #普及+#
【代码详解】
#include <bits/stdc++.h>
using namespace std;
const int N = 1005; // 定义最大节点数
int n, m; // n-节点数,m-关系组数
int board[N][N]; // 邻接矩阵表示图
int lvl[N]; // 存储每个节点的层级
int ans; // 存储最终结果(最大层级)
int num; // 临时变量,存储每组关系的节点数
int B[N]; // 标记数组,用于处理每组关系
int a, b, t; // 临时变量,用于输入处理
queue<int> qu; // 队列用于拓扑排序
// 计算节点x的入度
int du(int x)
{
int res = 0;
for (int i = 1; i <= n; i++)
res += board[i][x]; // 统计所有指向x的边
return res;
}
// 拓扑排序算法
void topo()
{
// 初始化:将所有入度为0的节点加入队列
for (int i = 1; i <= n; i++)
{
if (du(i) == 0)
{
lvl[i] = 1; // 初始层级为1
qu.push(i);
}
}
// 处理队列中的节点
while (qu.size())
{
int tmp = qu.front();
qu.pop();
// 遍历所有邻接节点
for (int i = 1; i <= n; i++)
{
if (board[tmp][i]) // 如果存在边tmp->i
{
board[tmp][i] = 0; // 删除这条边
if (du(i) == 0) // 如果i的入度变为0
{
lvl[i] = lvl[tmp] + 1; // 更新层级
qu.push(i);
}
}
}
}
}
int main()
{
cin >> n >> m;
// 处理每组关系
while (m--)
{
cin >> num;
memset(B, 0, sizeof(B)); // 清空标记数组
vector<int> st; // 存储该组的起始节点
vector<int> ed; // 存储该组的结束节点
// 输入该组的所有节点
cin >> a;
B[a] = 1;
st.push_back(a);
for (int i = 2; i < num; i++)
{
cin >> t;
st.push_back(t);
B[t] = 1;
}
cin >> b;
B[b] = 1;
st.push_back(b);
// 找出a和b之间未被标记的节点
for (int i = a + 1; i < b; i++)
{
if (B[i] == 0)
ed.push_back(i);
}
// 建立起始节点到结束节点的边
for (int i = 0; i < st.size(); i++)
{
for (int j = 0; j < ed.size(); j++)
{
board[st[i]][ed[j]] = 1;
}
}
}
// 执行拓扑排序
topo();
// 找出最大层级
for (int i = 1; i <= n; i++)
{
ans = max(ans, lvl[i]);
}
cout << ans << endl;
return 0;
}
【运行结果】
9 2
4 1 3 5 6
3 3 5 6
2
浙公网安备 33010602011771号