【题目描述】
一条单向的铁路线上,依次有编号为1、2、······、n的n个火车站。每个火车站都有一个级别,最低为1级。
现有若干趟车次在这条线路上行驶,每一趟都满足如下要求:
如果这趟车次停靠了火车站x,则始发站、终点站之间所有级别大于等于火车站x的都必须停靠(注意:起始站和终点站自然也算作事先已知需要停靠的站点)。
例如,下表是5趟车次的运行情况。其中,前4趟车次均满足要求,而第5趟车次由于停靠了3号火车站(2级)却未停靠途经的6号火车站(亦为2级)而不满足要求。
现有m趟车次的运行情况(全部满足要求),试推算这n个火车站至少分为几个不同的级别。
【输入描述】
第一行包含2个正整数n、m,用一个空格隔开;
第i+1行(1 ≤ i ≤ m)中,首先是一个正整数si(2 ≤ si ≤ n),表示第i趟车次有si个停靠站,接下来有si个正整数,表示所有停靠站的编号,从小到大排列。每两个数之间用一个空格隔开。输入保证所有的车次都满足要求。
【输出描述】
输出只有一行,包含一个正整数,即n个火车站最少划分的级别数。
【输入样例】
样例1:
9 2
4 1 3 5 6
3 3 5 6
样例2:
9 3
4 1 3 5 6
3 3 5 6
3 1 5 9
【输出样例】
样例1:
2
样例2:
3
对于20%的数据,1 ≤ n,m ≤ 10;
对于50%的数据,1 ≤ n,m ≤ 100;
对于100%的数据,1 ≤ n,m ≤ 1000。
都说用拓扑排序,但记忆化搜索依旧老当益壮:
源代码: #include<cstdio> #include<algorithm> using namespace std; int n,m,i[1001],f[1001],Next[1001][1001]; bool Vis[1001],Mark[1001][1001]; int DFS(int t) { if (f[t]) return f[t]; if (!Next[t][0]) return f[t]=1; for (int a=1;a<=Next[t][0];a++) { DFS(Next[t][a]); if (f[t]<f[Next[t][a]]+1) f[t]=f[Next[t][a]]+1; } return f[t]; } int main() { scanf("%d%d",&n,&m); for (int a=1;a<=m;a++) { int N; scanf("%d",&N); for (int b=1;b<=N;b++) { scanf("%d",&i[b]); Vis[i[b]]=true; } for (int b=i[1];b<=i[N];b++) if (!Vis[b]) for (int c=1;c<=N;c++) if (!Mark[b][i[c]]) { Mark[b][i[c]]=true; Next[b][++Next[b][0]]=i[c]; } for (int b=i[1];b<=i[N];b++) Vis[b]=false; } int ans=0; for (int a=1;a<=n;a++) if (!f[a]) ans=max(ans,DFS(a)); printf("%d",ans); return 0; }