【NOIP2013 普及组】车站分级
【NOIP2013 普及组】车站分级
一、题目
【NOIP2013 普及组】车站分级
时间限制: 1 Sec 内存限制: 128 MB
提交: 3 解决: 0
[提交][状态][讨论版]
题目描述
一条单向的铁路线上,依次有编号为 1, 2, …, n 的 n 个火车站。每个火车站都有一个级别,最低为 1 级。现有若干趟车次在这条线路上行驶,每一趟都满足如下要求:如果这趟车次停靠了火车站 x,则始发站、终点站之间所有级别大于等于火车站 x 的都必须停靠。(注意:起始站和终点站自然也算作事先已知需要停靠的站点)
例如,下表是 5 趟车次的运行情况。其中,前 4 趟车次均满足要求,而第 5 趟车次由于停靠了 3 号火车站(2 级)却未停靠途经的 6 号火车站(亦为 2 级)而不满足要求。
现有 m 趟车次的运行情况(全部满足要求),试推算这 n 个火车站至少分为几个不同的级别。
输入
输入文件为 level.in。
第一行包含 2 个正整数 n, m,用一个空格隔开。
第 i + 1 行(1 ≤ i ≤ m)中,首先是一个正整数 si(2 ≤ si ≤ n),表示第 i 趟车次有 si 个停靠站;接下来有 si个正整数,表示所有停靠站的编号,从小到大排列。每两个数之间用一个空格隔开。输入保证所有的车次都满足要求。
输出
输出文件为 level.out。
输出只有一行,包含一个正整数,即 n 个火车站最少划分的级别数。
样例输入
输入样例#1:
9 2
4 1 3 5 6
3 3 5 6
输入样例#2:
9 3
4 1 3 5 6
3 3 5 6
3 1 5 9
样例输出
输出样例#1:
2
输出样例#2:
3
提示
对于 20%的数据,1 ≤ n, m
≤ 10;
对于 50%的数据,1 ≤ n, m
≤ 100;
对于 100%的数据,1 ≤ n, m
≤ 1000。
二、分析及代码
首先考虑50%的数据,我们知道对于每一列车,它经过的站点中停了的站点的等级肯定比没停的站点高。因此对于每一辆车,我们可以把它经过的每一个没停的站点向每一个停了的站点建一条边。然后我们会得到一张图,在这张图上找最长的一条路段即可。
然后考虑正解,显然对于点考虑是无法再优化了,因此我们考虑车。我们定义一辆车的等级就是它经过站点的最小等级。我们考虑如何判定两辆车的等级大小。
对于两辆车,它们如果没有交点,那么它们的等级没有关系。
两辆车相交区间(都有停的区间)中,如果一辆车停的车辆多,那么它的等级低。
于是我们就建立了两辆车之间的大小关系,同样的,应用拓扑排序就可以找到这个最大的等级。
最后,还有一点要注意,因为我们处理的是车,而最后要求的是点。如果对于一辆等级为1的车,它经过的站点中如果有一个站点一辆车都没有停靠,那么最后的答案就要加1。
对于测试数据二:
9 3
4 1 3 5 6
3 3 5 6
3 1 5 9
比如第二辆车和第三辆车,都停了站5,但是第三辆车没有停3,所以第三辆车优先级比第二辆车高。
比如第一辆车和第二辆车的确有共同停靠站,且第一辆车停的站的确比第二辆车多,但是并不能说明第一辆车的等级低于第二辆车,因为起始站不同。
增加一辆每个站都停的列车,来作为等级最低的列车。
因为经过前面我们可以求出所有列车的等级,但是里面等级最低的一辆车要是有一个站没停,就存在着更低的一辆列车。这样才是正确的把点的等级转化为站的等级。
逻辑为:
在两辆车的最大共同区域里面,(1)有共同的站,(2)但是如果一辆车经过的站多,那么等级低。
问题分解为:
1、找两辆车的最大公共区域(好找,头里面的较大值,尾巴上的较小值)
2、计算公共区域里面的停靠站数
3、车辆数多的等级低
代码:
50分
- /*
- 分析:
- 低优先度节点指向高优先度节点
- */
- #include <iostream>
- #include <queue>
- #define Maxn 1005
- using namespace std;
- int n,m;
- // stopStation[i][j]表示第i辆车停靠的第j站, stopStation[i][0]表示第i辆车停靠的车站数
- int stopStation[Maxn][Maxn];
- // adjacentMatrix[i][j]为true表示j车站的优先级比i车站高
- // 停了的站的优先级比没停的高
- bool adjacentMatrix[Maxn][Maxn];
- bool station[Maxn];
- int inDegree[Maxn];
- //队列里面储存入度为0(也就是当前优先级最低)的节点的编号,
- queue<int> que;
- bool vis[Maxn];
- int priority[Maxn];
- int maxPriority;
- void readData(){
- cin>>n>>m;
- for(int i=;i<=m;i++){
- cin>>stopStation[i][];
- for(int j=;j<=stopStation[i][];j++){
- cin>>stopStation[i][j];
- }
- }
- }
- void printRead(){
- cout<<"n:"<<n<<" m:"<<m<<endl;
- for(int i=;i<=m;i++){
- for(int j=;j<=stopStation[i][];j++){
- cout<<stopStation[i][j]<<" ";
- }
- cout<<endl;
- }
- }
- void initArr_station(int i){
- for(int j=;j<=n;j++){
- station[j]=false;
- }
- for(int j=;j<=stopStation[i][];j++){
- int x=stopStation[i][j];
- station[x]=true;
- }
- }
- void printArr_station(){
- for(int j=;j<=n;j++){
- cout<<station[j]<<" ";
- }
- cout<<endl;
- }
- void initArr_adjacentMatrix(){
- for(int i=;i<=n;i++){
- for(int j=;j<=n;j++){
- adjacentMatrix[Maxn][Maxn]=false;
- }
- }
- //起点站之前的站是没有经过,但是优先级并不比那些停了的站低
- //所以我比较优先级只能从起点站开始
- //我也只能以终点站结束
- for(int i=;i<=m;i++){
- initArr_station(i);
- int endStation=stopStation[i][stopStation[i][]];
- for(int j=stopStation[i][];j<=endStation;j++){
- if(station[j]) continue;
- for(int k=stopStation[i][];k<=endStation;k++){
- if(station[k]){
- adjacentMatrix[j][k]=true;
- }
- }
- }
- }
- }
- void printArr_adjacentMatrix(){
- for(int i=;i<=n;i++){
- for(int j=;j<=n;j++){
- cout<<adjacentMatrix[i][j]<<" ";
- }
- cout<<endl;
- }
- }
- void initArr_inDegree(){
- for(int i=;i<=n;i++){
- inDegree[i]=;
- }
- for(int i=;i<=n;i++){
- for(int j=;j<=n;j++){
- if(adjacentMatrix[i][j]){
- inDegree[j]++;
- }
- }
- }
- }
- void printArr_inDegree(){
- for(int i=;i<=n;i++){
- cout<<inDegree[i]<<" ";
- }
- cout<<endl;
- }
- void initArr_vis(){
- for(int i=;i<=n;i++){
- vis[i]=false;
- }
- }
- void printArr_vis(){
- for(int i=;i<=n;i++){
- cout<<vis[i]<<" ";
- }
- cout<<endl;
- }
- void initArr_priority(){
- for(int i=;i<=n;i++){
- priority[i]=;
- }
- }
- void printArr_priority(){
- for(int i=;i<=n;i++){
- cout<<priority[i]<<" ";
- }
- cout<<endl;
- }
- void init(){
- readData();
- //printRead();
- //initArr_station(2);
- //printArr_station();
- initArr_adjacentMatrix();
- //printArr_adjacentMatrix();
- initArr_inDegree();
- //printArr_inDegree();
- initArr_vis();
- initArr_priority();
- //printArr_priority();
- }
- void removeConnection(int i1){
- for(int j=;j<=n;j++){
- adjacentMatrix[i1][j]=false;
- }
- }
- void topologicalSorting(){
- for(int i=;i<=n;i++){
- if(inDegree[i]==&&!vis[i]){
- vis[i]=true;
- que.push(i);
- priority[i]=;
- }
- }
- while(!que.empty()){
- int i1=que.front();
- que.pop();
- removeConnection(i1);
- initArr_inDegree();
- //printArr_inDegree();
- for(int i=;i<=n;i++){
- if(inDegree[i]==&&!vis[i]){
- vis[i]=true;
- que.push(i);
- priority[i]=priority[i1]+;
- }
- }
- }
- }
- void findHighestPriority(){
- maxPriority=;
- for(int i=;i<=n;i++){
- if(priority[i]>maxPriority){
- maxPriority=priority[i];
- }
- }
- }
- void printAns(){
- //printArr_priority();
- findHighestPriority();
- cout<<maxPriority<<endl;
- }
- int main(){
- freopen("4in.txt","r",stdin);
- init();
- topologicalSorting();
- printAns();
- return ;
- }
- /*
- 1、1,n不一定是起点和终点
- 起点站之前的站是没有经过,但是优先级并不比那些停了的站低
- 所以我比较优先级只能从起点站开始
- 2、起点终点不一定是从0开始
- */
80分,比较车的等级
- #include <iostream>
- #include <queue>
- using namespace std;
- //记录每辆车停的每个站 stopStation[i][0]表示第i辆车停靠的站
- int stopStation[][];
- int n,m;
- bool adjacentMatrix[][];
- //每一辆车的入度
- int inDegree[];
- bool vis[];
- //每一辆车的等级
- int priority[];
- //最大的等级,因为是从1开始,所以这个值就是答案
- int maxPriority;
- //队列里面储存入度为0(也就是当前优先级最低)的节点的编号,
- //用来做拓扑排序的队列
- queue<int> que;
- //读取数据
- void readData(){
- cin>>n>>m;
- for(int i=;i<=m;i++){
- cin>>stopStation[i][];
- for(int j=;j<=stopStation[i][];j++){
- cin>>stopStation[i][j];
- }
- }
- }
- //打印读取的数据
- void printRead(){
- cout<<"n:"<<n<<" m:"<<m<<endl;
- for(int i=;i<=m;i++){
- for(int j=;j<=stopStation[i][];j++){
- cout<<stopStation[i][j]<<" ";
- }
- cout<<endl;
- }
- }
- //增加一辆每个站都停的0号列车
- void initArr_stopStation(){
- stopStation[][]=n;
- for(int j=;j<=stopStation[][];j++){
- stopStation[][j]=j;
- }
- }
- //打印数据 stopStation
- void printArr_stopStation(){
- cout<<"n:"<<n<<" m:"<<m<<endl;
- for(int i=;i<=m;i++){
- for(int j=;j<=stopStation[i][];j++){
- cout<<stopStation[i][j]<<" ";
- }
- cout<<endl;
- }
- }
- //找两辆车(第i辆和第j辆)的最大公共区域(好找,头里面的较大值,尾巴上的较小值)
- void commonPathArea(int i,int j,int &start,int &end){
- int startI=stopStation[i][];
- int endI=stopStation[i][stopStation[i][]];
- int startJ=stopStation[j][];
- int endJ=stopStation[j][stopStation[j][]];
- start=max(startI,startJ);
- end=min(endI,endJ);
- }
- // 计算第i辆车公共区域[start、end]里面的停靠站数
- int stopStationNum(int i,int start,int end){
- int num=;
- for(int j=;j<=stopStation[i][];j++){
- if(stopStation[i][j]>end) break;
- if(stopStation[i][j]>=start&&stopStation[i][j]<=end) num++;
- }
- return num;
- }
- //比较i,j两辆车的等级
- int compareGrade(int i,int j){
- int start,end;
- commonPathArea(i,j,start,end);
- int numI=stopStationNum(i,start,end);
- int numJ=stopStationNum(j,start,end);
- if(numI==numJ) return ;
- else if(numI<numJ) return ;//i的等级高
- else if(numI>numJ) return -;
- }
- //初始化数据 adjacentMatrix
- void initArr_adjacentMatrix(){
- for(int i=;i<=m;i++){
- for(int j=;j<=m;j++){
- adjacentMatrix[i][j]=false;
- }
- }
- }
- //创建图
- void creatGraph(){
- for(int i=;i<=m-;i++){
- for(int j=i+;j<=m;j++){
- if(compareGrade(i,j)==) adjacentMatrix[j][i]=true;
- else if(compareGrade(i,j)==-) adjacentMatrix[i][j]=true;
- }
- }
- }
- //打印图
- void printGraph(){
- for(int i=;i<=m;i++){
- for(int j=;j<=m;j++){
- cout<<adjacentMatrix[i][j]<<" ";
- }
- cout<<endl;
- }
- }
- //初始化每辆车的入度
- void initArr_inDegree(){
- for(int i=;i<=m;i++)
- inDegree[i]=;
- }
- //打印每辆车的入度
- void printArr_inDegree(){
- for(int i=;i<=m;i++)
- cout<<inDegree[i]<<" ";
- cout<<endl;
- }
- //得到每辆车的入度
- void getInDegree(){
- for(int i=;i<=m;i++){
- for(int j=;j<=m;j++){
- if(adjacentMatrix[i][j]) inDegree[j]++;
- }
- }
- }
- //初始化数据vis
- void initArr_vis(){
- for(int i=;i<=m;i++)
- vis[i]=false;
- }
- //初始化数据 priority
- void initArr_priority(){
- for(int i=;i<=m;i++)
- priority[i]=;
- }
- //打印数组 priority
- void printArr_priority(){
- for(int i=;i<=m;i++)
- cout<<priority[i]<<" ";
- cout<<endl;
- }
- //取消节点i到其它节点的连接
- void removeConnection(int i){
- for(int j=;j<=m;j++){
- if(adjacentMatrix[i][j]) inDegree[j]--;
- }
- }
- //拓扑排序
- void topologicalSorting(){
- for(int i=;i<=m;i++){
- if(inDegree[i]==&&!vis[i]){
- vis[i]=true;
- que.push(i);
- priority[i]=;
- }
- }
- //printArr_priority();
- while(!que.empty()){
- int i1=que.front();
- que.pop();
- removeConnection(i1);
- for(int i=;i<=m;i++){
- if(inDegree[i]==&&!vis[i]){
- vis[i]=true;
- que.push(i);
- priority[i]=priority[i1]+;
- }
- }
- }
- }
- //找到最高优先级
- void findHighestPriority(){
- maxPriority=;
- for(int i=;i<=m;i++){
- if(priority[i]>maxPriority){
- maxPriority=priority[i];
- }
- }
- }
- //打印结果
- void printAns(){
- //printArr_priority();
- findHighestPriority();
- cout<<maxPriority<<endl;
- }
- //初始化
- void init(){
- //读取数据
- readData();
- //printRead();
- //初始化数据 stopStation()
- initArr_stopStation();//增加一辆每个站都停的0号列车
- //printArr_stopStation();
- //initArr_adjacentMatrix();
- //创建图
- creatGraph();
- //printGraph();
- //initArr_inDegree();
- //得到每辆车的入度
- getInDegree();
- //printArr_inDegree();
- //initArr_vis();
- //initArr_priority();
- }
- int main(){
- freopen("4in.txt","r",stdin);
- //初始化
- init();
- //拓扑排序
- topologicalSorting();
- //打印结果
- printAns();
- return ;
- }
90分 还是比较站的等级,输入时优化
- #include <iostream>
- #include <cstdio>
- #include <algorithm>
- #include <cstring>
- using namespace std;
- const int N=1e3+,INF=1e9+;
- inline int read(){
- char c=getchar();int x=,f=;
- while(c<''||c>''){if(c=='-')f=-;c=getchar();}
- while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
- return x*f;
- }
- int n,m,s,g[N][N],vis[N],lst[N],ind[N],ans=;
- int st[N],top=,buf[N],top2=;
- void toposort(){
- for(int i=;i<=n;i++) if(ind[i]==) st[++top]=i;
- while(top){
- ans++;//printf("hi %d %d\n",ans,del);
- while(top){
- int u=st[top--]; //printf("u %d\n",u);
- for(int v=;v<=n;v++) if(g[u][v]){
- ind[v]--; //printf("v %d %d\n",v,ind[v]);
- if(ind[v]==) buf[++top2]=v;
- }
- }
- for(int i=;i<=top2;i++) st[i]=buf[i];
- top=top2;
- top2=;
- }
- }
- //这是在读数据的时候就完成了各种初始化,减少了循环次数,所以可以多得分
- int main(){
- freopen("4in.txt","r",stdin);
- n=read();m=read();
- for(int i=;i<=m;i++){
- s=read();
- memset(vis,,sizeof(vis));
- for(int j=;j<=s;j++) lst[j]=read(),vis[lst[j]]=;
- for(int j=lst[];j<=lst[s];j++) if(!vis[j])
- for(int k=;k<=s;k++) if(!g[lst[k]][j]) g[lst[k]][j]=,ind[j]++;
- }
- toposort();
- printf("%d",ans);
- }
【NOIP2013 普及组】车站分级的更多相关文章
- [NOIp2013普及组]车站分级
思路: 对于每一趟车,将区间内所有经停的站和所有未经停的站连一条边,表示前者优先级一定高于后者,然后用Kahn跑一遍拓扑排序即可.然而这样会创造大量多余的边,会TLE1个点.考虑一种优化:因为每趟车本 ...
- Noip2013(普及组) 车站分级
题目描述 一条单向的铁路线上,依次有编号为 , , …, n 的 n 个火车站.每个火车站都有一个级别,最低为 级.现有若干趟车次在这条线路上行驶,每一趟都满足如下要求:如果这趟车次停靠了火车站 x, ...
- [NOIP2013] 普及组
计数问题 纯模拟 #include<cstdio> #include<iostream> using namespace std; int main(){ int n,x; c ...
- NOIP2013普及组 -SilverN
T1 计数问题 题目描述 试计算在区间 1 到 n 的所有整数中,数字 x(0 ≤ x ≤ 9)共出现了多少次?例如,在 1 到 11 中,即在 1.2.3.4.5.6.7.8.9.10.11 中, ...
- NOIP2013普及组 T2 表达式求值
OJ地址:洛谷P1981 CODEVS 3292 正常写法是用栈 #include<iostream> #include<algorithm> #include<cmat ...
- [NOIP2013 普及组] 表达式求值
[NOIP2013 普及组] 表达式求值 给定一个只包含加法和乘法的算术表达式,请你编程计算表达式的值. Input 一行,为需要你计算的表达式,表达式中只包含数字.加法运算符"+" ...
- 洛谷——P1980 [NOIP2013 普及组] 计数问题
题目描述 试计算在区间 11 到 nn的所有整数中,数字x(0 ≤ x ≤ 9)x(0≤x≤9)共出现了多少次?例如,在 11到1111中,即在 1,2,3,4,5,6,7,8,9,10,111,2, ...
- [NOIP2013]车站分级 解题报告
妈蛋这道普及组水(神)题搞了我非常久. 一. 首先一个非常显然的事情就是每一个火车告诉了站与站之间的等级关系,所以拓扑求最长路. 可是发现暴力建边的话最坏能够达到500*500,所以时间复杂度有O(M ...
- NOIP2002-2017普及组题解
虽然普及组一般都是暴力省一,但是有一些题目还是挺难的qwq个人觉得能进TG的题目会在前面打上'*' NOIP2002(clear) #include<bits/stdc++.h> usin ...
随机推荐
- python函数回顾:min()
描述 min() 方法返回给定参数的最小值,参数可以为序列. 语法 以下是 min() 方法的语法: min( x, y, z, .... ) 参数 x -- 数值表达式. y -- 数值表达式. z ...
- Python 网络编程——socket
一 客户端/服务器架构 客户端(Client)服务器(Server)架构,即C/S架构,包括 1.硬件C/S架构(打印机) 2.软件C/S架构(web服务) 理想/目标状态—— 最常用的软件服务器是 ...
- 设计一个算法,採用BFS方式输出图G中从顶点u到v的最短路径(不带权的无向连通图G採用邻接表存储)
思想:图G是不带权的无向连通图.一条边的长度计为1,因此,求带顶点u和顶点v的最短的路径即求顶点u和顶点v的边数最少的顶点序列.利用广度优先遍历算法,从u出发进行广度遍历,类似于从顶点u出发一层一层地 ...
- 虚拟机中的CentOS7如何上网?
进入文本插入编辑模式. 重点设置BOOTPROTO=dhcp,ONBOOT=yes即可. 修改完之后,先按Esc键,再按:键,然后输入wq,最后按回车键方可退出vim编辑器 在主机下,按win+R键, ...
- 交换机/路由器上的 S口 F口 E口
S口是serial接口的意思,也叫高速异步串口,主要是连接广域网的V.35线缆用的,说白了就是路由器和路由器连接时候用的,可以用命令设置带宽,一般也就在10M.8M左右.F口是FastEthernet ...
- 工作了3年的JAVA程序员应该具备什么技能?(转)
工作了3年的JAVA程序员应该具备什么技能? 因为和同事有约定再加上LZ自己也喜欢做完一件事之后进行总结,因此有了这篇文章.这篇文章大部分内容都是面向整个程序员群体的,当然因为LZ本身是做Java开发 ...
- 05 Spring框架 依赖注入(二)
上一节我们讲了三种信息的注入,满足一个类的属性信息的注入,但是如果我们需要向一个实例中注入另一个实例呢?就像我们创建一个学生类,里边有:姓名,性别,年龄,成绩等几个属性(我习惯把类的域叫做属性),但是 ...
- Springboot文件下载
https://blog.csdn.net/stubbornness1219/article/details/72356632 Springboot对资源的描述提供了相应的接口,其主要实现类有Clas ...
- ubuntu没有声音解决办法
cd /usr/lib/dbus-1.0/ chmod +x dbus-daemon-launch-helper sudo gpasswd -a $USER audio sudo killall pu ...
- @MarkFan 口语练习录音 20140423 [风雨哈佛路.Homeless To Harvard口语录音]
世界在转动,你只是一粒尘埃 没有你,世界照样在转 现实不会按照你的意识去改变的 一些人的需求 一些人的意志要比你更强 严酷的生活会让人不知所措 所以他们久久地困在挫败中 我们生气地抱怨,而对整体的形势 ...