题目描述

一条单向的铁路线上,依次有编号为 1, 2, …, n1,2,…,n的 nn个火车站。每个火车站都有一个级别,最低为 11 级。现有若干趟车次在这条线路上行驶,每一趟都满足如下要求:如果这趟车次停靠了火车站 xx,则始发站、终点站之间所有级别大于等于火车站xx 的都必须停靠。(注意:起始站和终点站自然也算作事先已知需要停靠的站点)

例如,下表是55趟车次的运行情况。其中,前44 趟车次均满足要求,而第 5 趟车次由于停靠了 3 号火车站(2级)却未停靠途经的 6号火车站(亦为 2 级)而不满足要求。

现有 mm 趟车次的运行情况(全部满足要求),试推算这nn 个火车站至少分为几个不同的级别。

解析

这题蛮好的,有助于更深入理解图论(可能吧),更有助于锻炼思维,如果可以的话,希望各位在独立思考出解法之前,能够多思考一下,反正我自己是想了一晚上。


首先分析题目,应该能很快发现每条线路对最终答案造成的影响。即,对于任意一条合法线路,其没有停靠的车站的等级恒小于其停靠过的车站的等级。

讲讲我的思路历程吧:

首先想到一种贪心,我们知道某条线路未停靠的点越少,其对最终答案的影响越小,但是经过尝试会发现这种贪心是有后效性的,不可行。

继而把思路引到图论上,图论的一个极其重要的作用大概就是维护一些抽象的关系以及限制条件,具体而明显地,比如并查集、网络流、差分约束等,其建模的本质是依靠题目中隐含的对象之间的某种关系。

那么这样想的话这题思路还是比较明显的,上面也提到过对于一条线路,其没有停靠的车站的等级恒小于其停靠过的车站的等级。这就是我们需要维护的关系。

这就很容易联想到拓扑排序,其维护的正是这种优先级大小关系。意即DAG中每一拓扑序的节点其等级大小是一致的。

我们感性地理解一下,题目告诉我们数据全部是满足要求的,实际上也就是告诉我们如果按照上面的思路建图,建出来必定是一个DAG(车站大小关系一定不会出现矛盾)。

题目要求最少划分的级别数,那我们只用使相邻拓扑序之间的节点等级差都只为1就可以了。

具体做法就是对于所有数据由等级小的车站向等级大的车站连有向边,再做一个拓扑排序就行了。

参考代码

代码略丑,实现比较简陋,如有疏漏望各位巨佬指出不足!

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<string>
#include<cstdlib>
#include<queue>
#include<vector>
#define INF 0x3f3f3f3f
#define PI acos(-1.0)
#define N 1010
#define MOD 2520
#define E 1e-12
using namespace std;
inline int read()
{
int f=1,x=0;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
return x*f;
}
vector<int> g[N];
int head[N],tot,n,m,ing[N],dat[N][N],c[N];
bool v[N][N];
int main()
{
n=read(),m=read();
for(int i=1;i<=m;++i){
int s=read();dat[i][0]=s;
for(int j=1;j<=s;++j) dat[i][j]=read();//读入数据
}
for(int i=1;i<=m;++i){
int now=dat[i][1]+1;
for(int j=2;j<=dat[i][0];++j){
while(now<dat[i][j]){
for(int k=1;k<=dat[i][0];++k)
//维护节点之间大小关系
if(!v[now][dat[i][k]]) g[now].push_back(dat[i][k]),ing[dat[i][k]]++,v[now][dat[i][k]]=1;
now++;
//注意及时排除已经确定的关系,否则会T
}
now++;
}
}
int ans=0;
queue<int> q;
for(int i=1;i<=n;++i)//拓扑排序
if(ing[i]==0) q.push(i),c[i]=1;
while(q.size()){
int x=q.front();q.pop();
for(int i=0;i<g[x].size();++i){
int y=g[x][i];
if(--ing[y]==0) c[y]=c[x]+1,ans=max(ans,c[y]),q.push(y);
}
}
cout<<ans<<endl;
return 0;
}

写完这题的一点个人感想

对于图论,很多看似无法用图论去做的题,实际上隐藏了许多暗示,可以用图论去维护某些信息,进而求解。个人认为,图论是一个下限很低但是上限挺高的一门学问,其蕴含的骚操作还是很多的。

P1983 车站分级[拓扑]的更多相关文章

  1. 洛谷 P1983 车站分级 拓扑排序

    Code: #include<cstdio> #include<queue> #include<algorithm> #include<cstring> ...

  2. 洛谷P1983 车站分级

    P1983 车站分级 297通过 1.1K提交 题目提供者该用户不存在 标签图论贪心NOIp普及组2013 难度普及/提高- 提交该题 讨论 题解 记录 最新讨论 求帮忙指出问题! 我这么和(diao ...

  3. 洛谷P1983车站分级

    洛谷\(P1983\)车站分级(拓扑排序) 目录 题目描述 题目分析 思路分析 代码实现 题目描述 题目在洛谷\(P1983\)上 ​ 题目: 一条单向的铁路线上,依次有编号为 \(1, 2, -, ...

  4. P1983 车站分级 思维+拓扑排序

    很久以前的一道暑假集训的题,忘了补. 感觉就是思维建图,加拓扑排序. 未停靠的火车站,必然比停靠的火车站等级低,就可以以此来建边,此处注意用vis来维护一下,一个起点和终点只建立一条边,因为不这样的话 ...

  5. 洛谷 P1983 车站分级

    题目链接 https://www.luogu.org/problemnew/show/P1983 题目描述 一条单向的铁路线上,依次有编号为 1,2,…,n的 n个火车站.每个火车站都有一个级别,最低 ...

  6. 洛谷P1983车站分级题解

    题目 这个题非常毒瘤,只要还是体现在其思维难度上,因为要停留的车站的等级一定要大于不停留的车站的等级,因此我们可以从不停留的车站向停留的车站进行连边,然后从入度为0的点即不停留的点全都入队,然后拓扑排 ...

  7. LG1983 「NOIP2013」车站分级 拓扑排序

    问题描述 LG1983 题解 考虑建立有向边\((a,b)\),代表\(a\)比\(b\)低级. 于是枚举每一辆车次经过的车站\(x \in [l,r]\),如果不是车辆停靠的车站,则从\(x\)向每 ...

  8. 【洛谷P1983 车站分级】

    这题好像是个蓝题.(不过也确实差不多QwQ)用到了拓扑排序的知识 我们看这些这车站,沿途停过的车站一定比未停的车站的级别高 所以,未停靠的车站向已经停靠的车站连一条边,入度为0的车站级别就看做1 然后 ...

  9. P1983车站分级

    %%%rqy 传送 我们注意到题目中这段话: 既然大于等于x的站都要停,那么不停的站的级别是不是都小于x?(这里讨论在始发站和终点站以内的站(注意这里是个坑)) 我们可以找出每趟车没停的站,向所有停了 ...

随机推荐

  1. java的字节码bytecode

    字节码名字的由来 字节码以一个字节即8bit为最小单位储存:字节码是java程序编译后的结果:字节码是一组8位字节为基础单位的二进制流 Java从源文件到执行的过程. 如何阅读JAVA字节码

  2. Python 获取文件类型后缀

    import os path='file.txt' file=os.path.splitext(path) filename,type=file print(filename) print(type)

  3. springmvc的注解配置

    springmvc大大减少了对xml的配置,减少了配置量,以及可以在一个controller类中进行多个请求配置 一.springmvc配置 context:component-scan 开启包扫描, ...

  4. python中的for循环加强

    #先执行外面for循环,再执行里面for循环,接着执行外面for循环,程序结束 #打印结果为1,10,2 flag=False for i in range(1,10): print(i) if fl ...

  5. 43 多线程(十三)——CAS(了解即可)

    emm...记一些关键词吧 原子操作 悲观锁.乐观锁 比较交换 硬件层面 C.C#底层实现 JUC = java.util.concurrent 高级并发才使用 面试会问到 了解即可 剩下的内容交给未 ...

  6. Python中的数据类型、变量、字符编码、输入输出、注释

    数据类型 number(数字) 用于存储类型,通常分为int.long.float.complex: int:32位机器上占32位,取值范围为-231 ~ 231 - 1:64位机器上占64位,取值范 ...

  7. VC6.0- C语言-winsocket-警告warning C4761

    错误介绍 操作系统:windows10 IDE:VC6.0 语言:C语言 项目内容简介:编写一个双人网络海战棋对战游戏 警告类型:警告warning C4761 integral size misma ...

  8. Linux 环境安装 Node、nginx、docker、vsftpd、gitlab

    Linux 环境安装 centos7 # 更新yum yum update -y 0. 防火墙 firewalld 新入的JD云服务器,发现防火墙默认是关闭的. # 查看防火墙状态 systemctl ...

  9. Windows MySql增量备份、完整备份采坑之路

    1.前言 这周公司交给我一个任务,负责项目Mysql数据库的备份,因为项目上线后数据是一个大问题,出了什么问题数据才是最大的问题,备份这时候就显得尤为重要, 公司项目的思路是:在项目系统设置内可以勾选 ...

  10. Java身份证处理工具

    身份证处理工具 /** * <html> * <body> * <P> Copyright 1994 JsonInternational</p> * & ...