NC16541 [NOIP2013]车站分级
题目
题目描述
一条单向的铁路线上,依次有编号为1, 2, …, n 的n 个火车站。每个火车站都有一个级别,最低为1 级。现有若干趟车次在这条线路上行驶,每一趟都满足如下要求:如果这趟车次停靠了火车站x,则始发站、终点站之间所有级别大于等于火车站x 的都必须停靠。(注意:起始站和终点站自然也算作事先已知需要停靠的站点)
例如,下表是5 趟车次的运行情况。其中,前4 趟车次均满足要求,而第5 趟车次由于停靠了3 号火车站(2 级)却未停靠途经的6 号火车站(亦为2 级)而不满足要求。
车站编号 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | ||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
车次/车站级别 | 3 | 1 | 2 | 1 | 3 | 2 | 1 | 1 | 3 | ||||||||
1 | 始 | → | → | → | 停 | → | → | → | 停 | → | 终 | ||||||
2 | 始 | → | → | → | 停 | → | 终 | ||||||||||
3 | 始 | → | → | → | → | → | → | → | 停 | → | → | → | → | → | → | → | 终 |
4 | 始 | → | 停 | → | 停 | → | 停 | → | 停 | → | 终 | ||||||
5 | 始 | → | → | → | 停 | → | → | → | → | → | → | → | 终 |
输入描述
第一行包含2个正整数n,m,用一个空格隔开。
第 i + 1 行(1 ≤ i ≤ m)中,首先是一个正整数 si(2 ≤ si ≤ n),表示第 i 趟车次有 si 个停靠站;接下来有si 个正整数,表示所有停靠站的编号,从小到大排列。
每两个数之间用一个空格隔开。输入保证所有的车次都满足要求。
输出描述
输出只有一行,包含一个正整数,即n个火车站最少划分的级别数。
示例1
输入
9 2 4 1 3 5 6 3 3 5 6
输出
2
示例2
输入
9 3 4 1 3 5 6 3 3 5 6 3 1 5 9
输出
3
备注
对于20%的数据,1 ≤n,m ≤10;
对于50%的数据,1 ≤n,m≤100;
对于100%的数据,1 ≤n,m ≤ 1000。
题解
知识点:图论建模,拓扑排序。
容易知道一条线路范围内的所有车站的级别关系,停靠站级别一定大于不停靠站。因此可以用一个虚拟点来模拟每条线路得到站点的大小关系,级别大的建一条边指向这个点,级别小的从这个点出发建一条边指向自己。用这个图拓扑排序,求排序的最大深度,即站点需要分为几个级别。需要注意的是,每层中间夹着虚拟点,如果深度从 开始计算,那么最后实际深度应该是 。
时间复杂度
空间复杂度
代码
#include <bits/stdc++.h> #define ll long long using namespace std; const int N = 1007 << 1, M = 1007 * 1007; int n, m; struct edge { int v, nxt; }e[M]; int h[N], idx; void add(int u, int v) { e[++idx] = { v,h[u] }; h[u] = idx; } int deg[N], dep[N]; queue<int> q; void toposort() { for (int i = 1;i <= n + m;i++) if (!deg[i]) q.push(i), dep[i] = 0; while (!q.empty()) { int u = q.front(); q.pop(); for (int i = h[u];i;i = e[i].nxt) { int v = e[i].v; dep[v] = dep[u] + 1; deg[v]--; if (!deg[v]) q.push(v); } } } int main() { std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); cin >> n >> m; for (int i = 1;i <= m;i++) { int s; cin >> s; vector<int> vis; for (int j = 1;j <= s;j++) { int u; cin >> u; vis.push_back(u); } for (int j = vis.front(), k = 0;j <= vis.back();j++) { if (j == vis[k]) { add(n + i, j); deg[j]++; k++; } else { add(j, n + i); deg[n + i]++; } } } toposort(); cout << *max_element(dep + 1, dep + n + m + 1) / 2 + 1 << '\n';///每个级别夹着一个站点,且深度从0计算 return 0; }
本文来自博客园,作者:空白菌,转载请注明原文链接:https://www.cnblogs.com/BlankYang/p/17020388.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧