题目描述
一条单向的铁路线上,依次有编号为 1,2,…,n的 n 个火车站。每个火车站都有一个级别,最低为 1 级。现有若干趟车次在这条线路上行驶,每一趟都满足如下要求:如果这趟车次停靠了火车站 x,则始发站、终点站之间所有级别大于等于火车站 x 的都必须停靠。(注意:起始站和终点站自然也算作事先已知需要停靠的站点)
例如,下表是 5 趟车次的运行情况。其中,前 4趟车次均满足要求,而第 5 趟车次由于停靠了 3 号火车站(2 级)却未停靠途经的 6 号火车站(亦为 2 级)而不满足要求。
现有 m 趟车次的运行情况(全部满足要求),试推算这 n 个火车站至少分为几个不同的级别。
输入格式
第一行包含 2 个正整数 n,m,用一个空格隔开。
第 i + 1 行(1 ≤ i ≤ m)中,首先是一个正整数 s_i(2 ≤ s_i ≤ n),表示第 i 趟车次有 s_i 个停靠站;接下来有 s_i 个正整数,表示所有停靠站的编号,从小到大排列。每两个数之间用一个空格隔开。输入保证所有的车次都满足要求。
输出格式
一个正整数,即 n 个火车站最少划分的级别数。
输入输出样例
输入 #1
9 2
4 1 3 5 6
3 3 5 6
输出 #1
2
输入 #2
9 3
4 1 3 5 6
3 3 5 6
3 1 5 9
输出 #2
3
说明/提示
对于 20%的数据,1 ≤ n, m ≤ 10;
对于50%的数据,1 ≤ n, m ≤ 100;
对于100%的数据,1 ≤ n, m ≤ 1000。
分析
题目中说,如果这趟车次停靠了火车站 x,则始发站、终点站之间所有级别大于等于火车站 x 的都必须停靠。也就是说,这趟车次经过且不停靠的所有车站的级别都必须小于这趟车次停靠的所有车站的级别。
可以确定他们之间的大小关系,停靠点站与不停靠的站连一条单向边,然后加入拓扑排序得出合法的他们之间的关系。
上代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int n,m,x,ans,a[1001][1001],v[1001],in[1001],h,t,q[1001],f[1001],b[1001];
void topsort()
{
memset(v,0,sizeof(v));
for(int i=1;i<=n;i++)
{
if(in[i]==0)//找到一个入度为0的边
{
t++;
q[t]=i;
f[i]=1;
v[i]=1;
}
}
while(h<t)
{
h++;
for(int i=1;i<=n;i++)
{
if(a[q[h]][i]==1&&v[i]==0)
{
in[i]--;
if(in[i]==0)
{
f[i]=f[q[h]]+1;
ans=max(ans,f[i]);
v[i]=1;
t++;
q[t]=i;
}
}
}
}
}
int main()
{
cin>>n>>m;
for(int i=1;i<=m;i++)
{
cin>>x;
memset(v,0,sizeof(v));
for(int j=1;j<=x;j++)
{
cin>>b[j];
v[b[j]]=1;
}
for(int j=b[1];j<=b[x];j++)
{
if(v[j]==0)
{
for(int k=1;k<=x;k++)
{
if(a[j][b[k]]==0)
{
in[b[k]]++;//入度++
a[j][b[k]]=1;//建边
}
}
}
}
}
topsort();
cout<<ans;
return 0;
}