洛谷1983 车站分级 [拓扑排序][建图]
题目描述
一条单向的铁路线上,依次有编号为 1,2,…,n 1 , 2 , … , n 的 n n 个火车站。每个火车站都有一个级别,最低为级。现有若干趟车次在这条线路上行驶,每一趟都满足如下要求:如果这趟车次停靠了火车站 x x ,则始发站、终点站之间所有级别大于等于火车站的都必须停靠。(注意:起始站和终点站自然也算作事先已知需要停靠的站点)
例如,下表是 5 5 趟车次的运行情况。其中,前趟车次均满足要求,而第 5 5 趟车次由于停靠了号火车站( 2 2 级)却未停靠途经的号火车站(亦为 2 2 级)而不满足要求。
现有趟车次的运行情况(全部满足要求),试推算这 n n 个火车站至少分为几个不同的级别。
输入格式
第一行包含个正整数 n,m n , m ,用一个空格隔开。
第 i+1 i + 1 行 (1≤i≤m) ( 1 ≤ i ≤ m ) 中,首先是一个正整数 si(2≤si≤n) s i ( 2 ≤ s i ≤ n ) ,表示第 i i 趟车次有个停靠站;接下来有 si s i 个正整数,表示所有停靠站的编号,从小到大排列。每两个数之间用一个空格隔开。输入保证所有的车次都满足要求。
输出格式
一个正整数,即 n n <script type="math/tex" id="MathJax-Element-23">n</script>个火车站最少划分的级别数。
题解
差分约束有没有想到[手动滑稽],反正我没想到
把起始站和终点站之间,停靠的站点向没停靠的站点连边,然后拓扑。就这么简单。(´థ౪థ)σ
代码
#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;
}
经验
- 含有等级限制的题目,可考虑:拓扑排序,树形结构,不等式关系