传送门
题目描述
一条单向的铁路线上,依次有编号为 1 , 2 , … , n 1, 2, …, n 1,2,…,n的 n n n个火车站。每个火车站都有一个级别,最低为 1 1 1 级。现有若干趟车次在这条线路上行驶,每一趟都满足如下要求:如果这趟车次停靠了火车站 x x x,则始发站、终点站之间所有级别大于等于火车站 x x x的都必须停靠。(注意:起始站和终点站自然也算作事先已知需要停靠的站点)
例如,下表是 5 5 5趟车次的运行情况。其中,前 4 4 4趟车次均满足要求,而第 5 5 5趟车次由于停靠了 3 3 3号火车站( 2 2 2级)却未停靠途经的 6 6 6号火车站(亦为 2 2 2级)而不满足要求。
现有 m m m趟车次的运行情况(全部满足要求),试推算这 n n n个火车站至少分为几个不同的级别。
输入格式
第一行包含 2 2 2个正整数 n , m n, m n,m,用一个空格隔开。
第 i + 1 i + 1 i+1 行 ( 1 ≤ i ≤ m ) (1 ≤ i ≤ m) (1≤i≤m)中,首先是一个正整数 s i ( 2 ≤ s i ≤ n ) s_i(2 ≤ s_i ≤ n) si(2≤si≤n),表示第 i i i 趟车次有 s i s_i si 个停靠站;接下来有 s i s_i si个正整数,表示所有停靠站的编号,从小到大排列。每两个数之间用一个空格隔开。输入保证所有的车次都满足要求。
输出格式
一个正整数,即 n n 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 % 20\% 20%的数据, 1 ≤ n , m ≤ 10 1 ≤ n, m ≤ 10 1≤n,m≤10;
对于 50 % 50\% 50%的数据, 1 ≤ n , m ≤ 100 1 ≤ n, m ≤ 100 1≤n,m≤100;
对于 100 % 100\% 100%的数据, 1 ≤ n , m ≤ 1000 1 ≤ n, m ≤ 1000 1≤n,m≤1000。
解题思路
拓扑排序+记录一下深度
Code
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
struct DT{
int to,next;
}a[500010];
int n,m,si,h,t,ans,num,f[10010],s[10010],ru[10010],q[100100],v[10010],sa[1100][1100],head[10010];
void add(int x,int y){
a[++num]=(DT){y,head[x]};
head[x]=num;
}
void tuop(){//拓扑
for(int i=1;i<=n;i++)
if(!ru[i])
q[++t]=i,f[i]=1;
while(h++<t)
for(int i=head[q[h]];i;i=a[i].next){
ru[a[i].to]--;
if(ru[a[i].to]<=0){
q[++t]=a[i].to;
f[a[i].to]=max(f[a[i].to],f[q[h]]+1);//下传深度
}
}
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
scanf("%d",&si);
memset(v,0,sizeof(v));
for(int j=1;j<=si;j++){
scanf("%d",&s[j]);
v[s[j]]=1;
}
for(int j=s[1];j<=s[si];j++)
if(!v[j])
for(int k=1;k<=si;k++)
sa[j][s[k]]=1;//没有停靠的向停靠的连边
}
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(sa[i][j]){
add(i,j);
ru[j]++;
}
tuop();
for(int i=1;i<=n;i++)
ans=max(ans,f[i]);
printf("%d",ans);
}