题目描述
一条单向的铁路线上,依次有编号为 1, 2, …, n 的 n 个火车站。每个火车站都有一个级别,最低为 1 级。现有若干趟车次在这条线路上行驶,每一趟都满足如下要求:如果这趟车次停靠了火车站 x,则始发站、终点站之间所有级别大于等于火车站 x 的都必须停靠。(注意:起始站和终点站自然也算作事先已知需要停靠的站点)例如,下表是 5 趟车次的运行情况。其中,前 4 趟车次均满足要求,而第 5 趟车次由于停靠了 3 号火车站(2 级)却未停靠途经的 6 号火车站(亦为 2 级)而不满足要求。现有 m 趟车次的运行情况(全部满足要求),试推算这 n 个火车站至少分为几个不同的级别。
【题目分析】
拓扑排序。
【代码】
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
int map[1001][1001],n,m,len[1001][1001];
int buk[1001],du[1001];
int now[5];
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=m;++i)
{
memset(buk,0,sizeof buk);
scanf("%d",&len[i][0]);
for (int j=1;j<=len[i][0];++j)
scanf("%d",&len[i][j]),buk[len[i][j]]++;
for (int j=len[i][1];j<=len[i][len[i][0]];++j)
{
if (!buk[j])
for (int k=1;k<=len[i][0];++k)
if (!map[len[i][k]][j])
{
// printf("ADD %d to %d du[%d]++\n",len[i][k],j,j);
map[len[i][k]][j]=1;
du[j]++;
}
}
}
queue<int>q;
int cnt=0;
for (int i=1;i<=n;++i)
if (du[i]==0)
{
q.push(i);
now[cnt&1]++;
// printf("%d IN\n",i);
}
while (!q.empty())
{
int x=q.front();q.pop();
now[cnt&1]--;
for (int i=1;i<=n;++i)
{
if (map[x][i])
{
// printf("du[%d]=%d\n",i,du[i]-1);
map[x][i]=1;
du[i]--;
if (du[i]==0)
{
q.push(i);
now[(cnt&1)^1]++;
}
}
}
if (now[cnt&1]==0) cnt++;
}
printf("%d\n",cnt);
}