题目:洛谷P1983、Vijos P1851、codevs3294。
题目大意:有一些车停靠某些站。现在要给所有站分级,规定一辆车停靠的所有站的最小级数必须大于(起点-终点)所有不停靠的站的最大级数。问至少分成几种不同的级数?
解题思路:由于停靠的站级数大于不停靠的站,我们把每列车停靠的站向不停靠的连一条有向边。
然后对其进行拓扑排序,拓扑序列的最大值就是答案。
注意在连边时先枚举不停靠的站,因为如果它停靠了就可以直接跳过循环,避免不必要的操作(反过来就TLE了)。
C++ Code:
#include<cstdio>
#include<cstring>
#include<cctype>
bool b[1011][1011],use[1011];
int n,m,d[1011],a[1011],ceng[1011],q[123457];
inline int readint(){
char c=getchar();
for(;!isdigit(c);c=getchar());
int p=0;
for(;isdigit(c);c=getchar())p=(p<<3)+(p<<1)+(c^'0');
return p;
}
int main(){
memset(d,0,sizeof d);
memset(b,0,sizeof b);
m=readint();
n=readint();
for(int i=1;i<=n;++i){
memset(use,0,sizeof use);
int num=readint();
for(int j=1;j<=num;++j)
use[a[j]=readint()]=true;
for(int k=a[1];k<=a[num];++k)
if(!use[k]){
for(int j=1;j<=num;++j)
if(!b[a[j]][k]){
b[a[j]][k]=true;
++d[k];
}
}
}
int l=0,r=0,ans=1;
memset(ceng,0,sizeof ceng);
for(int i=1;i<=m;++i)
if(!d[i])ceng[q[++r]=i]=1;
while(l!=r){
int u=q[++l];
for(int i=1;i<=m;++i)
if(b[u][i]&&!--d[i]){
ans=ceng[q[++r]=i]=ceng[u]+1;
}
}
printf("%d\n",ans);
return 0;
}