洛谷1983 车站分级 [拓扑排序][建图]
题目描述
一条单向的铁路线上,依次有编号为 的 个火车站。每个火车站都有一个级别,最低为 级。现有若干趟车次在这条线路上行驶,每一趟都满足如下要求:如果这趟车次停靠了火车站 ,则始发站、终点站之间所有级别大于等于火车站 的都必须停靠。(注意:起始站和终点站自然也算作事先已知需要停靠的站点)
例如,下表是 趟车次的运行情况。其中,前 趟车次均满足要求,而第 趟车次由于停靠了 号火车站( 级)却未停靠途经的 号火车站(亦为 级)而不满足要求。
现有 趟车次的运行情况(全部满足要求),试推算这 个火车站至少分为几个不同的级别。
输入格式
第一行包含 个正整数 ,用一个空格隔开。
第 行 中,首先是一个正整数 ,表示第 趟车次有 个停靠站;接下来有 个正整数,表示所有停靠站的编号,从小到大排列。每两个数之间用一个空格隔开。输入保证所有的车次都满足要求。
输出格式
一个正整数,即 个火车站最少划分的级别数。
题解
差分约束有没有想到[手动滑稽],反正我没想到
把起始站和终点站之间,停靠的站点向没停靠的站点连边,然后拓扑。就这么简单。(´థ౪థ)σ
代码
#include<iostream>
#include<cstdio>
#include<queue>
#define N 1000100
using namespace std;
int p[1010],s[1010],In[1010];bool Mark[1010][1010];
int End[N],Next[N],Last[N],cnt;
struct node{int id,step;};
queue<node>q;
void Ins(int x,int y){
if(Mark[x][y])return;
In[y]++;Mark[x][y]=true;
End[++cnt]=y,Next[cnt]=Last[x],Last[x]=cnt;
}
int main(){
int n,m,Ans=0;scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
int t,tot=0;scanf("%d",&t);
for(int j=1;j<=t;j++){
scanf("%d",&s[j]);
if(j==1)continue;
for(int k=s[j-1]+1;k<s[j];k++)p[++tot]=k;
}
for(int j=1;j<=t;j++)
for(int k=1;k<=tot;k++)Ins(s[j],p[k]);
}
for(int i=1;i<=n;i++)if(!In[i])q.push(node{i,1});
while(!q.empty()){
int t=q.front().id,st=q.front().step;
q.pop();Ans=max(Ans,st);
for(int i=Last[t];i;i=Next[i]){
int v=End[i];
if(!(--In[v]))q.push(node{v,st+1});
}
}
printf("%d",Ans);return 0;
}
经验
- 含有等级限制的题目,可考虑:拓扑排序,树形结构,不等式关系