【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分
1 /*
2 分析:3 低优先度节点指向高优先度节点4 */
5
6 #include
7 #include
8 #define Maxn 1005
9 using namespacestd;10 intn,m;11 //stopStation[i][j]表示第i辆车停靠的第j站, stopStation[i][0]表示第i辆车停靠的车站数
12 intstopStation[Maxn][Maxn];13 //adjacentMatrix[i][j]为true表示j车站的优先级比i车站高14 //停了的站的优先级比没停的高
15 booladjacentMatrix[Maxn][Maxn];16 boolstation[Maxn];17 intinDegree[Maxn];18 //队列里面储存入度为0(也就是当前优先级最低)的节点的编号,
19 queueque;20 boolvis[Maxn];21
22 intpriority[Maxn];23 intmaxPriority;24
25 voidreadData(){26 cin>>n>>m;27 for(int i=1;i<=m;i++){28 cin>>stopStation[i][0];29 for(int j=1;j<=stopStation[i][0];j++){30 cin>>stopStation[i][j];31 }32 }33 }34
35 voidprintRead(){36 cout<
45 void initArr_station(inti){46 for(int j=1;j<=n;j++){47 station[j]=false;48 }49 for(int j=1;j<=stopStation[i][0];j++){50 int x=stopStation[i][j];51 station[x]=true;52 }53 }54
55 voidprintArr_station(){56 for(int j=1;j<=n;j++){57 cout<
62 voidinitArr_adjacentMatrix(){63 for(int i=1;i<=n;i++){64 for(int j=1;j<=n;j++){65 adjacentMatrix[Maxn][Maxn]=false;66 }67 }68 //起点站之前的站是没有经过,但是优先级并不比那些停了的站低69 //所以我比较优先级只能从起点站开始70 //我也只能以终点站结束
71 for(int i=1;i<=m;i++){72 initArr_station(i);73 int endStation=stopStation[i][stopStation[i][0]];74 for(int j=stopStation[i][1];j<=endStation;j++){75 if(station[j]) continue;76 for(int k=stopStation[i][1];k<=endStation;k++){77 if(station[k]){78 adjacentMatrix[j][k]=true;79 }80 }81 }82 }83 }84
85 voidprintArr_adjacentMatrix(){86 for(int i=1;i<=n;i++){87 for(int j=1;j<=n;j++){88 cout<
94 voidinitArr_inDegree(){95 for(int i=1;i<=n;i++){96 inDegree[i]=0;97 }98 for(int i=1;i<=n;i++){99 for(int j=1;j<=n;j++){100 if(adjacentMatrix[i][j]){101 inDegree[j]++;102 }103 }104 }105 }106
107 voidprintArr_inDegree(){108 for(int i=1;i<=n;i++){109 cout<
114 voidinitArr_vis(){115 for(int i=1;i<=n;i++){116 vis[i]=false;117 }118 }119
120 voidprintArr_vis(){121 for(int i=1;i<=n;i++){122 cout<
127 voidinitArr_priority(){128 for(int i=1;i<=n;i++){129 priority[i]=0;130 }131 }132
133 voidprintArr_priority(){134 for(int i=1;i<=n;i++){135 cout<
140
141 voidinit(){142 readData();143 //printRead();144 //initArr_station(2);145 //printArr_station();
146 initArr_adjacentMatrix();147 //printArr_adjacentMatrix();
148 initArr_inDegree();149 //printArr_inDegree();
150 initArr_vis();151 initArr_priority();152 //printArr_priority();
153 }154
155 void removeConnection(inti1){156 for(int j=1;j<=n;j++){157 adjacentMatrix[i1][j]=false;158 }159 }160
161 voidtopologicalSorting(){162 for(int i=1;i<=n;i++){163 if(inDegree[i]==0&&!vis[i]){164 vis[i]=true;165 que.push(i);166 priority[i]=1;167 }168 }169 while(!que.empty()){170 int i1=que.front();171 que.pop();172 removeConnection(i1);173 initArr_inDegree();174 //printArr_inDegree();
175 for(int i=1;i<=n;i++){176 if(inDegree[i]==0&&!vis[i]){177 vis[i]=true;178 que.push(i);179 priority[i]=priority[i1]+1;180 }181 }182 }183 }184
185 voidfindHighestPriority(){186 maxPriority=0;187 for(int i=1;i<=n;i++){188 if(priority[i]>maxPriority){189 maxPriority=priority[i];190 }191 }192 }193
194 voidprintAns(){195 //printArr_priority();
196 findHighestPriority();197 cout<
200 intmain(){201 freopen("4in.txt","r",stdin);202 init();203 topologicalSorting();204 printAns();205 return 0;206 }207
208 /*
209 1、1,n不一定是起点和终点210 起点站之前的站是没有经过,但是优先级并不比那些停了的站低211 所以我比较优先级只能从起点站开始212 2、起点终点不一定是从0开始213 */
80分,比较车的等级
1 #include
2 #include
3 using namespacestd;4 //记录每辆车停的每个站 stopStation[i][0]表示第i辆车停靠的站
5 int stopStation[1005][1005];6 intn,m;7 bool adjacentMatrix[1005][1005];8 //每一辆车的入度
9 int inDegree[1005];10 bool vis[1005];11 //每一辆车的等级
12 int priority[1005];13 //最大的等级,因为是从1开始,所以这个值就是答案
14 intmaxPriority;15 //队列里面储存入度为0(也就是当前优先级最低)的节点的编号,16 //用来做拓扑排序的队列
17 queueque;18
19 //读取数据
20 voidreadData(){21 cin>>n>>m;22 for(int i=1;i<=m;i++){23 cin>>stopStation[i][0];24 for(int j=1;j<=stopStation[i][0];j++){25 cin>>stopStation[i][j];26 }27 }28 }29
30 //打印读取的数据
31 voidprintRead(){32 cout<
41 //增加一辆每个站都停的0号列车
42 voidinitArr_stopStation(){43 stopStation[0][0]=n;44 for(int j=1;j<=stopStation[0][0];j++){45 stopStation[0][j]=j;46 }47 }48
49 //打印数据 stopStation
50 voidprintArr_stopStation(){51 cout<
60 //找两辆车(第i辆和第j辆)的最大公共区域(好找,头里面的较大值,尾巴上的较小值)
61 void commonPathArea(int i,int j,int &start,int &end){62 int startI=stopStation[i][1];63 int endI=stopStation[i][stopStation[i][0]];64 int startJ=stopStation[j][1];65 int endJ=stopStation[j][stopStation[j][0]];66 start=max(startI,startJ);67 end=min(endI,endJ);68 }69
70 //计算第i辆车公共区域[start、end]里面的停靠站数
71 int stopStationNum(int i,int start,intend){72 int num=0;73 for(int j=1;j<=stopStation[i][0];j++){74 if(stopStation[i][j]>end) break;75 if(stopStation[i][j]>=start&&stopStation[i][j]<=end) num++;76 }77 returnnum;78 }79
80 //比较i,j两辆车的等级
81 int compareGrade(int i,intj){82 intstart,end;83 commonPathArea(i,j,start,end);84 int numI=stopStationNum(i,start,end);85 int numJ=stopStationNum(j,start,end);86 if(numI==numJ) return 0;87 else if(numI
88 else if(numI>numJ) return -1;89 }90
91 //初始化数据 adjacentMatrix
92 voidinitArr_adjacentMatrix(){93 for(int i=0;i<=m;i++){94 for(int j=0;j<=m;j++){95 adjacentMatrix[i][j]=false;96 }97 }98 }99
100 //创建图
101 voidcreatGraph(){102 for(int i=0;i<=m-1;i++){103 for(int j=i+1;j<=m;j++){104 if(compareGrade(i,j)==1) adjacentMatrix[j][i]=true;105 else if(compareGrade(i,j)==-1) adjacentMatrix[i][j]=true;106 }107 }108 }109
110 //打印图
111 voidprintGraph(){112 for(int i=0;i<=m;i++){113 for(int j=0;j<=m;j++){114 cout<
120 //初始化每辆车的入度
121 voidinitArr_inDegree(){122 for(int i=0;i<=m;i++)123 inDegree[i]=0;124 }125
126 //打印每辆车的入度
127 voidprintArr_inDegree(){128 for(int i=0;i<=m;i++)129 cout<
133 //得到每辆车的入度
134 voidgetInDegree(){135 for(int i=0;i<=m;i++){136 for(int j=0;j<=m;j++){137 if(adjacentMatrix[i][j]) inDegree[j]++;138 }139 }140 }141
142 //初始化数据vis
143 voidinitArr_vis(){144 for(int i=0;i<=m;i++)145 vis[i]=false;146 }147
148 //初始化数据 priority
149 voidinitArr_priority(){150 for(int i=0;i<=m;i++)151 priority[i]=0;152 }153
154 //打印数组 priority
155 voidprintArr_priority(){156 for(int i=0;i<=m;i++)157 cout<
161 //取消节点i到其它节点的连接
162 void removeConnection(inti){163 for(int j=0;j<=m;j++){164 if(adjacentMatrix[i][j]) inDegree[j]--;165 }166 }167
168 //拓扑排序
169 voidtopologicalSorting(){170 for(int i=0;i<=m;i++){171 if(inDegree[i]==0&&!vis[i]){172 vis[i]=true;173 que.push(i);174 priority[i]=1;175 }176 }177 //printArr_priority();
178 while(!que.empty()){179 int i1=que.front();180 que.pop();181 removeConnection(i1);182 for(int i=0;i<=m;i++){183 if(inDegree[i]==0&&!vis[i]){184 vis[i]=true;185 que.push(i);186 priority[i]=priority[i1]+1;187 }188 }189 }190 }191
192 //找到最高优先级
193 voidfindHighestPriority(){194 maxPriority=0;195 for(int i=0;i<=m;i++){196 if(priority[i]>maxPriority){197 maxPriority=priority[i];198 }199 }200 }201
202
203 //打印结果
204 voidprintAns(){205 //printArr_priority();
206 findHighestPriority();207 cout<
210 //初始化
211 voidinit(){212 //读取数据
213 readData();214 //printRead();215 //初始化数据 stopStation()
216 initArr_stopStation();//增加一辆每个站都停的0号列车217 //printArr_stopStation();218 //initArr_adjacentMatrix();219 //创建图
220 creatGraph();221 //printGraph();222 //initArr_inDegree();223 //得到每辆车的入度
224 getInDegree();225 //printArr_inDegree();226 //initArr_vis();227 //initArr_priority();
228
229 }230
231
232 intmain(){233 freopen("4in.txt","r",stdin);234 //初始化
235 init();236 //拓扑排序
237 topologicalSorting();238 //打印结果
239 printAns();240 return 0;241
242 }
90分 还是比较站的等级,输入时优化
1 #include
2 #include
3 #include
4 #include
5 using namespacestd;6 const int N=1e3+5,INF=1e9+5;7 inline intread(){8 char c=getchar();int x=0,f=1;9 while(c'9'){if(c=='-')f=-1;c=getchar();}10 while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}11 return x*f;12 }13 int n,m,s,g[N][N],vis[N],lst[N],ind[N],ans=0;14 int st[N],top=0,buf[N],top2=0;15 voidtoposort(){16 for(int i=1;i<=n;i++) if(ind[i]==0) st[++top]=i;17 while(top){18 ans++;//printf("hi %d %d\n",ans,del);
19 while(top){20 int u=st[top--]; //printf("u %d\n",u);
21 for(int v=1;v<=n;v++) if(g[u][v]){22 ind[v]--; //printf("v %d %d\n",v,ind[v]);
23 if(ind[v]==0) buf[++top2]=v;24 }25 }26 for(int i=1;i<=top2;i++) st[i]=buf[i];27 top=top2;28 top2=0;29 }30 }31
32 //这是在读数据的时候就完成了各种初始化,减少了循环次数,所以可以多得分
33 intmain(){34 freopen("4in.txt","r",stdin);35 n=read();m=read();36 for(int i=1;i<=m;i++){37 s=read();38 memset(vis,0,sizeof(vis));39 for(int j=1;j<=s;j++) lst[j]=read(),vis[lst[j]]=1;40 for(int j=lst[1];j<=lst[s];j++) if(!vis[j])41 for(int k=1;k<=s;k++) if(!g[lst[k]][j]) g[lst[k]][j]=1,ind[j]++;42 }43 toposort();44 printf("%d",ans);45 }