洛谷1983 车站分级 [拓扑排序][建图]

洛谷1983 车站分级 [拓扑排序][建图]

题目描述

一条单向的铁路线上,依次有编号为 1 , 2 , , n n 个火车站。每个火车站都有一个级别,最低为 1 级。现有若干趟车次在这条线路上行驶,每一趟都满足如下要求:如果这趟车次停靠了火车站 x ,则始发站、终点站之间所有级别大于等于火车站 x 的都必须停靠。(注意:起始站和终点站自然也算作事先已知需要停靠的站点)

例如,下表是 5 趟车次的运行情况。其中,前 4 趟车次均满足要求,而第 5 趟车次由于停靠了 3 号火车站( 2 级)却未停靠途经的 6 号火车站(亦为 2 级)而不满足要求。

img

现有 m 趟车次的运行情况(全部满足要求),试推算这 n 个火车站至少分为几个不同的级别。

输入格式

第一行包含 2 个正整数 n , m ,用一个空格隔开。

i + 1 ( 1 i m ) 中,首先是一个正整数 s i ( 2 s i n ) ,表示第 i 趟车次有 s i 个停靠站;接下来有 s i 个正整数,表示所有停靠站的编号,从小到大排列。每两个数之间用一个空格隔开。输入保证所有的车次都满足要求。

输出格式

一个正整数,即 n 个火车站最少划分的级别数。

题解

差分约束有没有想到[手动滑稽],反正我没想到

把起始站和终点站之间,停靠的站点向没停靠的站点连边,然后拓扑。就这么简单。(´థ౪థ)σ

代码

#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;
}

经验

  • 含有等级限制的题目,可考虑:拓扑排序,树形结构,不等式关系

猜你喜欢

转载自blog.csdn.net/ArliaStark/article/details/81193482