【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: names, values, assignment and mutability
推荐先看视频(youtube) Ned Batchelder - Facts and Myths about Python names and values - PyCon 2015 Change v ...
- 修改已生成项目app名称
在搜索里添加product Name,然后修改成你需要的app名称 修改完后可能会报错误如下 原因是test的测试路径发生了变化,其实如果不修改Test host的路径保留原来的重命名之前的app也是 ...
- 使用mybatis向oracle数据库插入数据异常
遇到了使用mybatis向oracle数据库插入数据异常的问题, 具体的报错如下:org.springframework.jdbc.UncategorizedSQLException: ### Err ...
- GPU instancing
参考 https://www.cnblogs.com/hont/p/7143626.html github地址 https://github.com/yingsz/instancing/ 补充2点: ...
- Python3.6全栈开发实例[010]
10.有字符串 "k:1|k1:2|k2:3|k3:4" 处理成字典 {'k':1,'k1':2....} s = "k:1|k1:2|k2:3|k3:4" d ...
- 入坑第二式 golang入坑系列
史前必读: 这是入坑系列的第二式,如果错过了第一式,可以去gitbook( https://andy-zhangtao.gitbooks.io/golang/content/ )点个回放,看个重播.因 ...
- zabbix-2.4.8-1添加MySQL状态监控
1.安装zabbix-agentyum -y install zabbix-2.4.8-1.el6.x86_64.rpm zabbix-agent-2.4.8-1.el6.x86_64.rpm 安装以 ...
- hadoop学习第四天-Writable和WritableComparable序列化接口的使用&&MapReduce中传递javaBean的简单例子
一. 为什么javaBean要继承Writable和WritableComparable接口? 1. 如果一个javaBean想要作为MapReduce的key或者value,就一定要实现序列化,因为 ...
- Fidder详解之抓包
前言 本文是博主发表的第一篇文章,如有傻逼之处,请大家见谅.最近遇到很多人说接口相关的问题,比如:什么是接口,我该怎么做接口测试,还有我总是抓不到APP上的https请求(这个巨坑,不知道坑了多少小白 ...
- 关于java登录界面
import java.awt.*; 包含用于创建用户界面和绘制图形图像的所有类. import javax.swing.*; 提供一组“轻量级”(全部是 Java 语言)组件,尽量让这些组件在所 ...