[NOIP2013 普及组] 车站分级-题解
题目简述:一条单向的铁路线上,依次有编号为 的 个火车站。每个火车站都有一个级别,最低为 级。现有若干趟车次在这条线路上行驶,每一趟都满足如下要求:如果这趟车次停靠了火车站 ,则始发站、终点站之间所有级别大于等于火车站 的都必须停靠。(注意:起始站和终点站自然也算作事先已知需要停靠的站点)
现有 趟车次的运行情况(全部满足要求),试推算这 个火车站至少分为几个不同的级别。
若存在该车次 ,
对于车次 :车站 的级别一定小于车站 的级别的最大值;
对于车次 :车站 的级别一定小于车站 的级别的最大值;否则车站的划分级别将不成立。
由此,我们可以将这 个车站进行划分
这样的话,令 的级别为最小的 ,则 就为 。
若增加车次 ,
则有新的划分方式,其中 一定小于 的级别的最大值。
我们发现这已经很明显的分出来了级别, 就是其答案。
建模:
对于每班车,也只是会影响在这班车的终点站和起点站之间(包含)的车站的级别。
我们将一定小于(到达的车站的级别)的车站[1]向到达的车站进行连边,然后得到其最深的节点的深度。
由于此图是一个 ,所以利用 拓扑+DP 的方式解决。
(另外,你也可以使用一些高端的数据结构或其他,来优化这个 的建图。)
用 代替了 四个点,否则这个图就太麻烦了。
其中 与 的位置不会对答案产生影响,因为题目对其的限制较小,但由于题目中并没有说到 小于 的情况,所以分级是上图 的情况。
#include <bits/stdc++.h>
using namespace std;
const int N = 1010, inf = 1e9 + 7;
int n, m, s, ans, d[N], in[N], f[N];
bool vis[N], g[N][N];
queue <int> q;
int main()
{
cin >> n >> m;
for (int i = 1; i <= m; ++ i)
{
cin >> s;
for (int j = 1; j <= s; ++ j)
{
cin >> d[j];
vis[d[j]] = true;
}
for (int j = d[1]; j <= d[s]; ++ j)
{
if (! vis[j])
{
for (int k = 1; k <= s; ++ k)
{
if (!g[j][d[k]])
{
++ in[d[k]];
}
g[j][d[k]] = true;
}
}
}
for (int i = 1; i <= n; ++ i)
{
vis[i] = false;
}
}
for (int i = 1; i <= n; ++ i)
{
f[i] = -inf;
if (in[i] == 0)
{
q.push(i);
f[i] = 1;
}
}
while (!q.empty())
{
int u = q.front();
q.pop();
for (int v = 1; v <= n; ++ v)
{
if (g[u][v] && in[v])
{
f[v] = max(f[v], f[u]+1);
in[v] --;
if (in[v] == 0)
{
q.push(v);
}
}
}
}
for (int i = 1; i <= n; ++ i)
{
ans = max(ans, f[i]);
}
cout << ans << '\n';
return 0;
}
指的是这班车所跨域的车站中的。 ↩︎
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】